Reputation: 1025
Iv'e recently started a new project and decided to give Angular 2 a chance. As a former Backbone developer, I am now facing types of work which are really new to me.
I am trying to build a very simple app: I want to have a class room object, and within it a list of students. In my point of view, each of them (classroom, student) should be different components, such that each component has it's own template.
I wish to have the templates completely separated, and on the classroom template to loop through the students and render the student template.
For instance: My classroom component would like like that: import {Component, OnInit} from '@angular/core'; import {Student} from 'app/student.component';
@Component({
selector : 'classroom',
templateUrl : 'app/classroom.component.html',
directives : [Classroom]
})
export class MainContainer implements OnInit {
students : Student[]; // assume I have an array of students here
constructor() {}
}
The Classroom template would look:
<div>
<student *ngFor="let student of students"></student>
</div>
The Student component:
import {Component, Input, Output} from '@angular/core';
@Component({
selector : 'student',
templateUrl : 'build/component/main-box/student.component.html'
})
export class Student {
name : string;
id: number;
grade:number;
constructor() {
}
};
And the student template, as simple as:
<div>
name : {{name}}
id : {{id}}
grade : {{grade}}
</div>
But the above code shows me nothing. Seems like the student data is not passed to the student object. Iv'e seen some examples that passed the entire object down, this way:
[student]="student"
But it feels really wrong. In Backbone for instance, I would render the parent view, and inside it append all the child views. Here it feels odd.
Another solution Iv'e seen is to simply add the student template to the classroom template, instead of holding them in separate files. I must say that I really really don't like this practice since I believe that these components should'nt live together in the same file.
Another things, what doest @Input()
stand for? I did not really understand from the docs why @Input()
gives access to data.
At this point I am more confused than not :] I would really appreciate some tips and your feedback and learn some good practices for dealling such tasks.
Thanks a lot!
Upvotes: 2
Views: 2415
Reputation: 5087
Each instance of your <student>
tag has an associated Student
object that contains its data. As currently written, however, that Student
object doesn't get any data from anywhere - it just sits there with empty values. Angular does not assume anything about where you want its data to come from, there are all sorts of possibilities and it doesn't want to get in the way.
So, you have to tell Angular where you want your Student
objects to get their data from. @Input
is one way to do that. When you tag a component's member variable with @Input
, you are telling Angular that the value for that variable should come from the same-name property of the associated template tag. If you don't specify @Input
, Angular will not make any relation between the property and the variable.
Having done that, you then need to actually supply said property. For example, to provide the value for an @Input name
, you would put [name]="someName"
in the <student>
tag.
The directive *ngFor="let student of students"
does not set any property. It creates a variable named student
that is available in that tag's scope in the template, but is not automatically used anywhere else, even in child templates. The snippet [student]="student"
would assign that variable to the property of the same name, which the student template would then be able to use as an @Input
variable.
I could be wrong, but I don't think adding [student]="student"
to your code as is would actually work. Maybe Angular would recognize the matching name and replace the whole component object, but I don't think so.
What you should do is separate your data and component classes. So you'd have Student
as a data class with the fields as written but no annotation, and let's say StudentDisplay
with the @Component
annotation and an @Input
member variable of type Student
. Then hook up that variable to a property, and write the student template in terms of that variable.
Upvotes: 4