angularjs - Angular 2: Trouble with Custom Components -


i trying custom component working within angular 2 written es6/es7 , transpiled babel.

when load page, component accordion of appropriate data present, of panels shut , clicking nothing. modelling accordion after typescript plunker. additionally, removedynamic() function appcomponent toggles when click button view not update show change in data. @ loss after spending better part of yesterday , today tinkering it. insight appreciated!

i have appcomponent defined such, appropriate template:

import {component, view} 'angular2/core'; // import component , view constructor (for metadata) import {http_providers} 'angular2/http'; // we're using http in our  import {accordion, accordiongroup} '../components/accordion/accordion.component';  // import ngfor directive import {ngfor} 'angular2/common';  // annotate appcomponent class `component` @component({   selector: 'my-app',    // let angular know `http`   providers: [http_providers] })   // define view of our `component` using 1 or more // `view` annotations @view({    // link our external template file   templateurl: './components/app.html',    // specify directives our `component` utilize   // `directive` property of `view` annotation   directives: [accordion, accordiongroup, ngfor] })  export class appcomponent {   constructor() {      // debug     console.log('appcomponent constructor() go');      this.isopen = false;      this.groups = [       {         heading: 'dynamic 1',         content: 'i dynamic!'       },       {         heading: 'dynamic 2',         content: 'i dynamic well'       }     ];   }    removedynamic() {     this.groups.pop();      // debug     console.log('removedynamic() run');   } };  //export {appcomponent}; 

the template appcomponent:

<p>   <button type="button" class="btn btn-default" (click)="removedynamic()">     remove last dynamic   </button> </p>  <accordion>   <accordion-group heading="this header" is-open="true">     content   </accordion-group>   <accordion-group [heading]="group.heading" *ngfor="#group of groups">     {{group.content}}   </accordion-group>   <accordion-group heading="another group" [is-open]="isopen">     more content   </accordion-group> </accordion> 

my angular app bootstrapped elsewhere due webpack.

i have custom accordion component written using angular 2 es6/es7:

// import inject, component , view constructor (for metadata) import {inject} 'angular2/core'; import {component, view} 'angular2/core'; // import ngclass directive import {ngclass} 'angular2/common';  // # accordion component  // annotate accordion class `component` @component({   // define how can use our `component` annotation   // `selector` property.    selector: 'accordion, [accordion]',    // modify `host` element css class designator   host: {     'class': 'panel-group'   } })  // define view of our `component` using 1 or more // `view` annotations @view({    // link our external template file   templateurl: './components/accordion/accordion.html' })  // create , export `component` class export class accordion {    constructor() {     // debug     console.log('accordion constructor() go');      this.groups = [];   }    // function register groups   addgroup(group) {     this.groups.push(group);   }    closeothers(opengroup) {     this.groups.foreach((group) => {       if(group !== opengroup) {         group.isopen = false;       }     });   }    removegroup(group) {     let index = this.groups.indexof(group);      if(index !== -1) {       this.groups.splice(index, 1);     }   } }  // # accordiongroup component  // annotate accordiongroup class `component` @component({   selector: 'accordion-group, [accordion-group]',    // specify (with `inputs` property) using `heading`   // attribute in our  component mapped `heading`   // variable in our `component`.   inputs: ['heading', 'isopen'],    // let angular know `providers`   providers: [] })  // define view of our `component` using 1 or more // `view` annotations @view({    // link our external template file   templateurl: './components/accordion/accordion-group.html',    // specify directives our `component` utilize   // `directive` property of `view` annotation   directives: [ngclass, accordion] })  // create , export `component` class export class accordiongroup {    constructor(accordion) {     // debug     console.log('accordiongroup constructor() go');      this._isopen = false;      this.accordion = accordion;      this.accordion.addgroup(this);   }    // angular 2 di desugar'd   // reference: https://stackoverflow.com/questions/33026015/how-to-inject-angular2-http-service-into-es6-7-class   /*static parameters() {     return [[accordion]];   }*/    toggleopen(event) {     event.preventdefault();     this.isopen = !this.isopen;     this.accordion.closeothers(this);   }    ondestroy() {     this.accordion.removegroup(this);   } }  // above desugar'd angular 2 di should work, doesn't. // line seems accomplish looking though. accordiongroup.parameters = [[accordion]];  //export {accordion, accordiongroup}; 

this template accordion component:

<ng-content></ng-content> 

and template accordiongroup component:

<div class="panel panel-default" [ngclass]="{'panel-open': isopen}">   <div class="panel-heading" (click)="toggleopen($event)">     <h4 class="panel-title">       <a href tabindex="0"><span>{{heading}}</span></a>     </h4>   </div>   <div class="panel-collapse" [hidden]="!isopen">     <div class="panel-body">       <ng-content></ng-content>     </div>   </div> </div> 

as aside, lot of code came particular tutorial demonstrates of angular 2 stuff typescript, adapted es6/es7 environment webpack | migrating directives angular 2

update: have attempted both of answers submitted , neither has solved problem of view not updating.

here screen capture of how component behaving:

the proper data present, yet view isn't updating

and of debug logs showing data manipulation:

the appropriate data manipulation present, @ loss

i @ loss here guys, , can't use typescript :(

edited following mark's comment

in fact, it's way angular2 handles change detection. "when change detection runs , dirty checks object, checking see if object reference changed (it not check see if contents of object changed)." (from mark's comment)

(if you're interested in way zones used in angular2, have @ great answer mark: what angular2 equivalent angularjs $watch?).

so need refactor bit removedynamic method:

export class appcomponent {   (...)    removedynamic() {     this.groups.pop();      this.groups = this.groups.slice();      // debug     console.log('removedynamic() run');   } } 

see answer regarding use of slice method:

here answer angular team regarding behavior: https://github.com/angular/angular/issues/6458.

hope helps you, thierry


Comments