Angular 2: a problem with custom components

I am currently trying to get a custom component running in Angular 2 written with ES6 / ES7 and passed in using Babel.

When I load the page, I get a component accordion with all the relevant data, but all the panels are closed and clicking does nothing. I model my accordion after this TypeScript Plunker . In addition, the removeDynamic () function from AppComponenttoggles when you click the button, but the view is not updated to show the data change. I’m at a loss, having spent most of yesterday and mess with him today. Any insight would be greatly appreciated!

I have mine AppComponent, defined as such, with the appropriate pattern:

import {Component, View} from 'angular2/core'; // Import Component and View constructor (for metadata)
import {HTTP_PROVIDERS} from 'angular2/http'; // We're using http in our

import {Accordion, AccordionGroup} from '../components/accordion/accordion.component';

// Import NgFor directive
import {NgFor} from 'angular2/common';

// Annotate AppComponent class with `Component`
@Component({
  selector: 'my-app',

  // Let Angular know about `Http`
  providers: [HTTP_PROVIDERS]
})


// Define the view of our `Component` using one or more
// `View` annotations
@View({

  // Link to our external template file
  templateUrl: './components/app.html',

  // Specify which directives our `Component` will utilize with
  // the `directive` property of the `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 am dynamic!'
      },
      {
        heading: 'Dynamic 2',
        content: 'I am dynamic as well'
      }
    ];
  }

  removeDynamic() {
    this.groups.pop();

    // Debug
    console.log('removeDynamic() run');
  }
};

//export {AppComponent};

AppComponent:

<p>
  <button type="button" class="btn btn-default" (click)="removeDynamic()">
    Remove last dynamic
  </button>
</p>

<accordion>
  <accordion-group heading="This is the header" is-open="true">
    This is the 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 - Webpack.

Accordion, Angular 2 ES6/ES7:

// Import Inject, Component and View constructor (for metadata)
import {Inject} from 'angular2/core';
import {Component, View} from 'angular2/core';
// Import NgClass directive
import {NgClass} from 'angular2/common';

// # Accordion Component

// Annotate Accordion class with `Component`
@Component({
  // Define how we can use our `Component` annotation with
  // the `selector` property. 
  selector: 'accordion, [accordion]',

  // Modify the `host` element with a css class designator
  host: {
    'class': 'panel-group'
  }
})

// Define the view of our `Component` using one or more
// `View` annotations
@View({

  // Link to our external template file
  templateUrl: './components/accordion/accordion.html'
})

// Create and export `Component` class
export class Accordion {

  constructor() {
    // Debug
    console.log('Accordion constructor() go');

    this.groups = [];
  }

  // Function to 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 with `Component`
@Component({
  selector: 'accordion-group, [accordion-group]',

  // Specify (with the `inputs` property) that we are using a `heading`
  // attribute in our  component which will be mapped to a `heading`
  // variable in our `Component`.
  inputs: ['heading', 'isOpen'],

  // Let Angular know about any `providers`
  providers: []
})

// Define the view of our `Component` using one or more
// `View` annotations
@View({

  // Link to our external template file
  templateUrl: './components/accordion/accordion-group.html',

  // Specify which directives our `Component` will utilize with
  // the `directive` property of the `View` annotation
  directives: [NgClass, Accordion]
})

// Create and 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 get parameters() {
    return [[Accordion]];
  }*/

  toggleOpen(event) {
    event.preventDefault();
    this.isOpen = !this.isOpen;
    this.accordion.closeOthers(this);
  }

  onDestroy() {
    this.accordion.removeGroup(this);
  }
}

// The above desugar'd Angular 2 DI should work, but doesn't. This
// line seems to accomplish what we are looking for though.
AccordionGroup.parameters = [[Accordion]];

//export {Accordion, AccordionGroup};

Accordion:

<ng-content></ng-content>

AccordionGroup:

<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>

, Angular 2 TypeScript, es6/es7 Webpack | Angular 2

: .

, :

Own data is present, but the view is not updated

, :

Appropriate data manipulations are present, but I'm at a loss

, , TypeScript: (

+2
2

Mark

, Angular2 . " , , , , ( , )". ( Mark)

( Angular2, Mark: Angular2 AngularJS $?).

, removeDynamic:

export class AppComponent {
  (...)

  removeDynamic() {
    this.groups.pop();

    this.groups = this.groups.slice();

    // Debug
    console.log('removeDynamic() run');
  }
}

. slice:

Angular : https://github.com/angular/angular/issues/6458.

, , Thierry

+3

barebone, plnkr.

@Component({
  selector: 'my-app',
  providers: [],
  template: `
      <div class="panel panel-default" [ngClass]="{'panel-open': isOpen}">
        <div class="panel-heading" (click)="toggleOpen($event)">
          <h4 class="panel-title">
          </h4>
        </div>
        <div class="panel-collapse" [ngClass]="{'hidden': isOpen}">
          <div class="panel-body">
            <h3>geee</h3>
          </div>
        </div>
      </div>
  `,
  directives: [NgClass]
})
export class App {
  public isOpen = false;

  public groups = [
    {
      heading: 'Dynamic 1',
      content: 'I am dynamic!'
    },
    {
      heading: 'Dynamic 2',
      content: 'I am dynamic as well'
    }
  ];

  constructor(){
    this.isOpen = false;
    this.groups = [
      {
        heading: 'Dynamic 1',
        content: 'I am dynamic!'
      },
      {
        heading: 'Dynamic 2',
        content: 'I am dynamic as well'
      }
    ];
  }
  toggleOpen(event) {
    event.preventDefault();
    this.isOpen = !this.isOpen;
    //this.accordion.closeOthers(this);
  }

}

http://plnkr.co/edit/MjQ0GDimtqi20zmrDAEB?p=preview

0

Source: https://habr.com/ru/post/1626981/


All Articles