Reputation: 880
I have a model like this:
export class Person{
name: string;
}
Which is used in my component as follow:
export class TestComponent {
@Input() person : Person;
constructor() {
}
}
I want to set person name from html as below:
<app-test [person.name]="'Jack'"</app-test>
When I do so, angular gets angry that : "Can't bind to 'person.name' since it isn't a known property of 'app-test'."
well, he is right somehow, person is property of my component, not person.name
On the other hand, we don't get any error in following sample:
<span [style.color]="'red'">This span is red.</span>
Am I moving against rules??
Or is style property internally different? How?
Thanks
Upvotes: 2
Views: 2713
Reputation: 635
That is because style
is directive with multiple selectors and inputs.
You can achieve this by having some directive that would do the job. I guess you could make something similar to this: (Not tested)
import { Directive, ViewContainerRef, ChangeDetectorRef, OnInit } from '@angular/core';
const selector = `
[name],
[name.foo],
[name.bar]
`;
export const inputs = [
'name',
'name.foo',
'name.bar'
];
@Directive({
selector,
inputs
})
export class HelloDirective implements OnInit {
constructor(
private viewContainerRef: ViewContainerRef
) {
}
ngOnInit(): void {
const getSetKeys = Object.keys(this).filter(item => inputs.indexOf(item) > -1);
const getValues = getSetKeys.map(item => this[item]);
const component = this.viewContainerRef['_view'].component;
getSetKeys.forEach((item, index) => {
const splitKey = item.split('.');
component[splitKey[0]][splitKey[1]] = getValues[index];
})
}
}
In this case, you could use your directive as
<some-component [name.foo]="'Some foo'" [name.bar]="'Some bar'"></some-component>
and this would inject to your "name" object in component.
I would not recommend this way but it is possible to implement it.
Upvotes: 0
Reputation: 141
Its because the Input property you are try to pass to the Test Component is "person.name", which isn't defined on your Test component. Your Test component expects something named "person". Secondly you are passing a string and not a Person type you defined on the Test Component. Change the Test component to accept a string or pass the Person and reference the name property in the Test component. And make sure the names match.
Here is two ways you can think about passing the person's name to the other component
<app-test [name]="person.name" [person]="person"></app-test>
Then in the Test Component:
export class TestComponent {
@Input() name: string;
@Input() person : Person;
}
Notice how the names and types match? My advice would be dont pass more than you need. If you just need the Person name passed, just have your component accept a string. No need to pass the whole object.
TestComponent Template:
<h1>Person: {{person.name}}</h1>
<h1>Name: {{name}}</h1>
I am going to add a link to the Angular Documentation as I think its a pretty important part of Angular you might want to review. The Heroes tutorial they have is really good.
https://angular.io/api/core/Input
Upvotes: 1
Reputation: 57909
You're correct [ngStyle] is different and [style] is different, You need
<app-test [person]="{name:'Jack'}"</app-test>
Other options are
<app-test [person]="person"</app-test>
And in your main.app
this.person.name='Jack'
Remember that, if you use an object in a input any change of a property of the object in parent or in child change the "properties" of the object
Upvotes: 1