2016-01-29 111 views
2

我目前正在嘗試使用ES6/ES7編寫Angular 2中的自定義組件,並使用Babel進行編譯。Angular 2:自定義組件故障

當我加載頁面時,我得到了組件手風琴與所有適當的數據存在,但所有面板都關閉,點擊什麼都不做。我在TypeScriptPlunker之後爲我的手風琴建模。此外,當您單擊該按鈕時,AppComponent中的removeDynamic()函數會切換,但視圖不會更新以顯示數據更改。我在昨天花了大部分時間和今天的修補之後,感到很茫然。任何有識之士將非常感謝!

我有我的AppComponent定義爲這樣的,有一個合適的模板:

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> 

我的角度應用在別處自舉因的WebPack。

我採用了棱角分明2 ES6/ES7編寫自定義Accordion組件:

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

作爲一個asi de,很多代碼都來自這個特別的教程,它演示了TypeScript的所有Angular 2的東西,所以我簡單地將它改編到我的es6/es7環境中,使用Webpack | Migrating Directives to Angular 2

更新:我已經嘗試了兩個提交的答案,並且都沒有解決視圖不更新的問題。

這裏是如何將組件目前表現抓屏:

The proper data is present, yet the view isn't updating

的調試日誌顯示的數據操縱和另一:

The appropriate data manipulation is present, but I am at a loss

我很茫然這裏的傢伙,我真的不能使用TypeScript :(

回答

0

我得到了準系統版本在這個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

如果我改變了'AccordionGroup'模板,這一點,它沒有任何渲染,看似。 –

+0

它只是上面的片段,我改變了.. – inoabrian

+0

不,我看你改變了,謝謝你。我會試一試。 –

3

編輯馬克的評論

其實下面,它的Angular2處理變化檢測的方式。 「當更改檢測運行並且髒檢查對象時,它通過檢查對象引用是否更改(它不檢查對象的內容是否更改)來執行此操作。「(馬克的評論)

(如果你有興趣在區域在Angular2使用的方式,你可以看看馬克偉大的答案:What is the Angular2 equivalent to an AngularJS $watch?)。

所以你需要重構一個位你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

希望它可以幫助你, 蒂埃裏

+0

雖然這可能修復了'removeDynamic'功能,但點擊時我的內容仍然不會顯示,而且由於某些原因,該按鈕仍然不會更新視圖。在每次調用函數時使用'console.log(this.groups)',即使使用我的原始函數,也會從數組中刪除數據,但由於某些原因,視圖並未更新。無論如何,我真的很感謝幫助。 –

+2

「對象內的更新不會觸發更改檢測」 - 我會對此稍加區別。更改檢測始終在事件觸發後運行(由於Zone.js掛鉤,事件觸發更改檢測)。我會改寫如下:當更改檢測運行並且它檢查對象時,它通過檢查對象引用是否更改(它不檢查對象的內容是否更改)來執行此操作。 –

+0

你絕對是對的。我的句子含糊不清!非常感謝您指出這一點;-)我通過引用您的話更新了我的答案... –