Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

View doesn't update on component property change in Angular 2 RC6 first time

I have a component in my project that calls a service to retrieve some (locally-stored) JSON, which is mapped to an array of objects and returned to the component to be displayed. The problem I am having is that the bindings in the view don't seem to update the first time I call the service, but do update the second time I call the service.

The component template:

@Component({
    selector: 'list-component',
    template: `
        <button type="button" (click)="getListItems()">Get List</button>
        <div>
            <table>
                <tr>
                    <th>
                        ID
                    </th>
                    <th>
                        Name
                    </th>
                    <th>
                        Job Title
                    </th>
                </tr>
                <tr *ngFor="let employee of _employees">
                    <td>
                        {{employee.id}}
                    </td>
                    <td>
                        {{employee.name}}
                    </td>
                    <td>
                        {{employee.jobTitle}}
                    </td>
                </tr>
            </table>
        </div>
    `,
    changeDetection: ChangeDetectionStrategy.Default
})

The component controller class:

export class ListComponent {

    _employees: Employee[];

    constructor(
        private employeeService: EmployeeService
    ) {

    }

    getListItems() {
        this.employeeService.loadEmployees().subscribe(res => {
            this._employees = res;
        });
    }
}

And the service:

@Injectable()
export class EmployeeService {

    constructor(
        private http: Http
    ) { }

    loadEmployees(): Observable<Employee[]> {
        return this.http.get('employees.json')
         .map(res => <Employee[]>res.json().Employees);
    }
}

Things I've tried:

  • Changing the ChangeDetectionStrategy to OnPush
  • Making the _employees property an observable, populating it with this._employees = Observable<Employee[]> and using the async pipe on the ngFor statement: *ngFor="let employees of _employees | async" - same situation, only populates on second button click

Can anyone spot anything wrong with my code, or are aware of any issues with RC6 that could lead to such behaviour?

like image 988
dgkane Avatar asked Sep 13 '16 09:09

dgkane


People also ask

How does angular detect changes in a component?

So Angular has two functions each specializing on a particular node definition and calls them at different stages when checking a component: Both these functions are executed each time Angular performs change detection for a component and the parameters to the function are supplied by the change detection mechanism.

How to set default values for angular 2 component?

Below I had detailly elaborated in a comprehensive way on how to set default values for Angular 2 component. First code the .html file with respect to requirements. Then include the default property in the child component. Now initialize the property with a default value using the @Input () decorator.

How to update the text content of a span in angular?

You don’t have to do anything else for the span, but for the b-comp you need to indicate that it receives textContent property: Now, whenever the AText property changes on the A component Angular will automatically update the property textContent on B component and span. It will also call ngOnChanges lifecycle hook for the child component.

How to pass data from parent component to child component in angular?

As you probably know Angular provides template syntax for property bindings - . This syntax is generic so it can be applied for both child components and native DOM elements. So if you want to pass some data to the child b-comp and span from the parent A component you do it like this in the component’s template:


1 Answers

I had same issue. Still didn't get any solid solution. Using detectChanges works. Below is the workaround but please note that this is not the perfect solution

export class ListComponent {

_employees: Employee[];

constructor(
    private employeeService: EmployeeService,  private chRef: ChangeDetectorRef
) {

}

getListItems() {
    this.employeeService.loadEmployees().subscribe(res => {
        this._employees = res;
        this.chRef.detectChanges()
    });
}

}

like image 120
Imamudin Naseem Avatar answered Sep 28 '22 14:09

Imamudin Naseem