-
Notifications
You must be signed in to change notification settings - Fork 118
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(angular): 2-way data-binding for inlined Inputs #533
base: main
Are you sure you want to change the base?
Conversation
Hm, for some reason I'm not able to reproduce the bug, but it might be because I'm using the Not doubting that the issue is real, just curiosis why the error is occuring. Thanks for helping to resolve bugs :) |
That would explain why you didn't catch this one, I am using |
Unless I'm missing something, binding property value works for me (with Angular Module): <bq-progress
enable-tooltip
thickness="large"
[value]="progressValue"
></bq-progress> export class AppComponent implements AfterViewInit {
progressValue = 20;
ngAfterViewInit() {
this.updateProgress();
}
updateProgress() {
const intervalId = setInterval(() => {
this.progressValue++;
if (this.progressValue > 100) {
clearInterval(intervalId);
}
}, 250);
}
} I'm using angular({
componentCorePackage,
outputType: 'component', // Generate many component wrappers tied to a single Angular module (lazy/hydrated approach)
directivesProxyFile: resolve(__dirname, '../beeq-angular/src/directives/components.ts').replace(/\\/g, '/'),
directivesArrayFile: resolve(__dirname, '../beeq-angular/src/directives/index.ts').replace(/\\/g, '/'),
valueAccessorConfigs: angularValueAccessorBindings,
customElementsDir: 'dist/components'
}), Here 👉🏼 is a code sandbox with the code example but I'm really curious about this and if there is a way to see/get a reproduction case. As mentioned before, maybe I'm missing something or the issue is related to something else different from what I've mentioned above (and if that's the case, my apologies 🙂 ). |
@dgonzalezr This bug is specific to the new experimental angular({
componentCorePackage,
outputType: 'component', // Generate many component wrappers tied to a single Angular module (lazy/hydrated approach)
directivesProxyFile: resolve(__dirname, '../beeq-angular/src/directives/components.ts').replace(/\\/g, '/'),
directivesArrayFile: resolve(__dirname, '../beeq-angular/src/directives/index.ts').replace(/\\/g, '/'),
valueAccessorConfigs: angularValueAccessorBindings,
customElementsDir: 'dist/components',
inlineProperties: true
}) |
Thank you @alexandertrefz for clarifying it 🙌🏼 . After testing the new experimental |
Looking at it more I found that it is unrelated to If using getters and setters resolves the problem that could be a solution, but it would be even better if they are never included in the final output (leaving the generated js the same regardless of the value of |
Playing around with the target setting in typescript, I found that by setting the Not saying that this is a perfect solution, but just to verify |
@kristilw I have applied the following changes based in your comment, and indeed worked for me with the new experimental config 🤷🏼♂️ I have no doubt that @alexandertrefz solutions could be the right approach, I'm just leaving some feedback so that all cases can be considered 🙂 |
Now I had the time to test this similarly. I have indeed been using But indeed, I am undecided which approach is better, on one hand, just changing the compilation options seems like a cleaner solution, that has less code duplication, etc. At the very least it is good to know that it is possible to make it work, with the current version! Thanks @kristilw! |
Thought I had found a nice solution by using the "declare" keyword infront of the property assigment like this: class MyComponent {
declare prop: string;
} but the Angular If we arent able to completely remove the properties then using getters and setters seemes like a nice solution 👍 My only suggestion is that (if I understand the code correctly) there isn't any point in writing the full implementation of the getter and setter functions (because they will be overwritten by the @ProxyCmp decorator, and having the implementation written in two different places is confusing). I think the only thing needed to get the typing working is this: class MyComponent {
set prop(_: Components.MyComponent['prop']) { }
} I did a brief test and it seemed to work in my project (just tested a single property by manually editing the proxies.ts file in our build). What do you think @alexandertrefz ? |
@kristilw You are going through the exact same attempts that i've tried :D I think leaving it empty is reasonable, as long as the compiler doesn't complain. I'll try this shorter option out, it seems like a decent improvement. Edit: Seems to work just fine for me, I would be happy to adjust the PR. |
@alexandertrefz mind rebasing the PR? |
@christian-bromann Yes, apologies, I got quite tied up with work. I'll update & rebase it later today. |
e6ff47d
to
f036d29
Compare
Pull request checklist
Please check if your PR fulfills the following requirements:
npm run build
) was run locally for affected output targetsnpm test
) were run locally and passednpm run prettier
) was run locally and passedPull request type
Please check the type of change your PR introduces:
What is the current behavior?
When using the new
inlineProperties
configuration option, properties only update correctly when they are used unbounded(<my-component prop="value" />
), on the angular side. Bound(<my-component [prop]="componentProperty" />
) properties are not synced correctly.What is the new behavior?
Properties work correctly, no matter if they are used bound or unbounded.
Does this introduce a breaking change?
General Information
PR #497 by @kristilw introduced a long awaited fix for Angular, allowing the Angular Language Server to pick up the types of inputs correctly.
The change works correctly on the Typescript side, as well as at runtime, if the input properties are unbound. However, if they are bound the Angular Compiler does something that prevents the binding to work at all (at runtime), even though the Decorator establishing the getter and setter to pass the value along to the Web Component underneath is run correctly.
This is caused (for some reason) by the property being declared on the class itself, after compilation, like this:
However, in order for typescript to create the type in such a way that the (badly implemented) Angular Language Service can pick up the types correctly, we need to declare them on the class.
The solution is to inline the getter and setter for the inputs directly, allowing Angular to pick up the type correctly, and the internal binding to the web component to work correctly as well.
This PR also changes the type of the
el
property, so that it reflects the accurate Web Component type, instead of the genericHTMLElement
.