2

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!

1 Answer 1

4

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.

Sign up to request clarification or add additional context in comments.

6 Comments

Great, it works, but is there any other way to do that? I'm just curious
Thanks for your answer though, I'll leave it open until tomorrow just to hear more opinions, and will approve it if none come :)
@superuser123 If you inline the child template in the same file instead of having it separate, the student variable from the ngFor directive would be in scope and could be used directly without a property. Other than that, all I can think of is various ways to be pointlessly convoluted.
@superuser123 You could hook up each field individually, with [name]="student.name" etc., but that's a lot of duplication and repetition for no benefit.
yes it sounds a bit over kill...well, its surprising that Angular team never gave this too much attention..
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.