Exploring the hierarchical structure of components in Angular2 with nested templates

Recently embarking on a new project, I decided to dive into Angular 2. Coming from a background in Backbone development, I find myself encountering unfamiliar challenges.

The goal is to create a simple app where there is a classroom object with a list of students. Each component (classroom and student) should have its own template for better organization.

I envision the templates being completely separated, with the classroom template iterating through the students and rendering the student template.

For example, the structure would look like this:

@Component({
  selector      :   'classroom',
  templateUrl   :   'app/classroom.component.html',
  directives    :   [Classroom]
})

export class MainContainer implements OnInit {
  students : Student[]; // assuming an array of students here
  constructor() {}
}

The Classroom template:

<div>
    <student *ngFor="let student of students"></student>
</div>

The Student component:

@Component({
  selector      :   'student',
  templateUrl   :   'build/component/main-box/student.component.html'
})

export class Student {
  name : string;
  id: number;
  grade:number;
  constructor() {
  }
};

The student template:

<div>
      name : {{name}}
      id : {{id}}
      grade : {{grade}}
</div>

However, when implementing the code above, no data shows up. It appears that the student data is not being passed correctly to the student object. I've seen examples passing the entire object down like this:

[student]="student"

But it doesn't feel right. In my experience with Backbone, I would render the parent view and then append the child views inside it. This approach feels strange to me.

Another suggestion I came across was simply adding the student template to the classroom template instead of keeping them in separate files. Personally, I strongly disagree with this practice as I believe each component should have its own file.

Additionally, what does @Input() signify? I couldn't quite grasp from the documentation why @Input() grants access to data.

At this juncture, I find myself more confused than clear-headed. Any tips, feedback, or best practices for tackling these tasks are greatly appreciated!

Thank you!

Answer №1

element, each <student> tag is linked to a corresponding Student object that contains its data. However, the current setup leaves the Student object empty without any actual data. Angular doesn't assume where this data should come from, leaving it open to various possibilities. To specify where the data for the Student objects should be sourced, you can use the @Input decorator. By using @Input on a component's member variable, you inform Angular that the value for that variable will be retrieved from a property with the same name in the associated template tag. If no @Input is specified, Angular won't establish a connection between the property and the variable. When setting up the property, such as @Input name, you would utilize syntax like [name]="someName" within the <student> tag. Although directive
*ngFor="let student of students"</code creates a scoped variable named <code>student</code in the template, it doesn't automatically set any property. Assigning this variable to an <code>@Input
property labeled the same way, such as [student]="student", allows the student template to access it. It might not work effectively by directly adding [student]="student" in your code. It's suggested to separate the data and component classes - creating a plain data class like
Student</code without annotations, and another one called <code>StudentDisplay</code with the <code>@Component
annotation and an @Input member variable of type Student. This way, you can link the variable to a property and structure the student template accordingly.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for assigning multiple Angular2 variables in Jquery on change

I am having trouble assigning more than one variable in jQuery within Angular2. Here is my current code: jQuery('.source-select').on('change',(e) => this.updateForm.value.sources = jQuery(e.target).val().split('--')[0]); ...

The GUI does not reflect changes observed in Angular

Even though I have subscribed in names.component to a subject that triggers when the subject is changed, my GUI does not react to the "lang" change. Why is this happening? This component resides in fields.module.ts and the CacheService is provided by the ...

Typescript not being transpiled by Webpack

As I set out to create a basic website, I opted to utilize webpack for packaging. TypeScript and SASS were my choice of tools due to their familiarity from daily use. Following the documentation at https://webpack.js.org, I encountered issues with loaders ...

What is the correct way to use Observables in Angular to send an array from a Parent component to a Child

Initially, the task was to send JSON data from the parent component to the child component. However, loading the data through an HTTP request in the ngOnInit event posed a challenge as the data wasn't being transmitted to the child component. Here is ...

Creating a dynamic name in TypeScript for an object to be utilized in an onClick event

If I have a TypeScript object declared in my view like this: <script type="text/javascript"> var myTSObject = Module.CustomClass('#someId'); myISObject.bind(); </script> Now, if I need to manage a click event from within the ...

What is the most effective method for handling numerous HTTP requests upon the initialization of an application?

Within my Angular application, I am facing the challenge of executing multiple (6) HTTP requests from different sources during initialization. Currently, I am using app_initializer and promise.all() to achieve this. However, the issue lies in the fact that ...

Getting nested component value in Angular 2: A step-by-step guide

I have a component for items and a component for quantities with buttons to increase and decrease the quantity. My goal is to increment a private value inside the <quantity-component> and access this quantity value when I call addToCart() from the &l ...

What is causing the .responseToString function to be recognized as not a function?

Consider the following scenario with Typescript: interface IResponse { responseToString(): string; } export default IResponse; We have two classes that implement this interface, namely RestResponse and HTMLResponse: import IResponse from "./IRespo ...

Contrasts between { [P in keyof any]: number } and { [P in string | number | symbol]: number }

As a newcomer to TypeScript, I've noticed a discrepancy between keyof any and string | number | symbol in MappedType. However, I'm unclear on the exact distinction between these two syntaxes. type T = keyof any; //string | number | symbol type T ...

Aligning validation schema with file type for synchronization

Below is the code snippet in question: type FormValues = { files: File[]; notify: string[]; }; const validationSchema = yup.object({ files: yup .array<File[]>() .of( yup .mixed<File>() .required() .t ...

Unveiling the magic: Dynamically displaying or concealing fields in Angular Reactive forms based on conditions

In my current scenario, there are three types of users: 1. Admin with 3 fields: email, firstname, lastname. 2. Employee with 4 fields: email, firstname, lastname, contact. 3. Front Office with 5 fields: email, firstname, lastname, airline details, vendo ...

Assigning a Boolean value of false in JavaScript will result in it being evaluated as true

I'm struggling to understand why my variable continues to evaluate as true and enters the IF block, even after I specifically assign it as false. let isSetToFalse = this.model.hasQ1; console.log('type ', typeof this.model.hasQ1) //I find it ...

Troubleshooting Vue and Typescript: Understanding why my computed property is not refreshing the view

I'm struggling to understand why my computed property isn't updating the view as expected. The computed property is meant to calculate the total price of my items by combining their individual prices, but it's only showing me the initial pri ...

How to bring in a class that was exported using `export = uuid` in Typescript

I'm facing a challenge while working with the node_module called uuid-js in TypeScript. After installing both the module and its typings, I am unsure how to properly import the module. Question: What is the correct way to import the module? The func ...

Angular dynamic array implementation

Essentially, I have an API that returns data when a search is performed. I store this data in an array and display it using ngFor in my HTML. However, whenever I attempt a new search, the same function is called but the HTML does not update to show the ne ...

What is the correct way to set the default function parameter as `v => v` in JavaScript?

function customFunction<T, NT extends Record<string, string | number | boolean>>( data: T, normalize?: (data: T) => NT, ) { const normalizedData = normalize ? normalize(data) : {}; return Object.keys(normalizedData); } customFuncti ...

Transforming named functions in const or class constructors with Eslint and Typescript: a guide

Lately, I've been relying heavily on the code snippet from an answer that I requested: function sameValuesAsKeys<K extends string>(...values: K[]): {readonly [P in K]: P} { const ret = {} as {[P in K]: P} values.forEach(k => ret[k] = k); ...

Update the configuration to change the localization code for Angular to a different language

Getting my angular application ready for localization is a top priority. I need to make sure that the different languages are working seamlessly before publishing. { "$schema": "./node_modules/@angular/cli/lib/config/schema.json", ...

The exported interface's property '<properyName>' is utilizing a private name '<name>'

Here is a new interface declaration: export interface ApiClientMetodOptions { initialFilterSatement?: string; fieldsMapping?: { [K in keyof P]?: string; }; requestParams?: IRequestParams<P>; additionalParams?: { [ ...