2017-01-10 8 views
1

this post을 따라 Angular의 1.5 구성 요소 postLink 이벤트를 알게되었습니다.

나는 plunker에서 일하고있다.

controller: function() { 
this.$onInit = function() { 
    console.log("$onInit"); 
    this.tabs = []; 
}; 
this.addTab = function addTab(tab) { 
    console.log("addTab"); 
    this.tabs.push(tab); 
}; 
this.selectTab = function selectTab(index) { 
    for (var i = 0; i < this.tabs.length; i++) { 
    this.tabs[i].selected = false; 
    } 
    this.tabs[index].selected = true; 
}; 
this.$postLink = function() { 
    console.log("$postLink. nr of tabs added: " + this.tabs.length); 

    this.selectTab(this.selected); 
}; 
} 

콘솔 출력 :

  • $의 onInit
  • addTab
  • addTab
  • addTab
  • $ POSTLINK 다음 탭 구성 요소에 대한 코드입니다. nr 개의 탭이 추가됨 : 3

그러나 타이프 스크립트에서 동일한 작업을 시도하면 postLink 이벤트가 너무 빨리 트리거됩니다. 탭을 구성 요소에 추가하기 전에 트리거됩니다.

여기에 코드의 일부입니다 : /tabs/tab/tab.component.ts

namespace MainApp { 
const mainApp = angular.module("mainApp"); 

class TabComponent implements ng.IComponentOptions { 
    public templateUrl: string | ng.Injectable<(...args: any[]) => string>; 
    public controller: any; 
    public controllerAs: string; 
    public transclude: boolean; 
    public bindings: any; 
    public require: any; 

    constructor() { 
     this.templateUrl = ["rootUrl", (rootUrl) => rootUrl + "app/uitrijregelingBerekening/tabs/tab/tab.html"]; 
     this.controller = TabController; 
     this.transclude = true; 
     this.bindings = { 
      label: "@", 
     }; 
     this.require = { 
      tabs: "^^", 
     }; 
    } 
} 

mainApp.component("tab", new TabComponent()); 

} 

/tabs/tab/tab.controller.ts

namespace MainApp { 
interface ITabBindings { 
    label: string; 
} 

export class TabController implements ITabBindings { 
    public label: string; 
    private tabs: TabsController; 

    public tab: any; 

    constructor() { 
    } 

    public $onInit() { 
     this.tab = { 
      label: this.label, 
      selected: false 
     }; 
     this.tabs.addTab(this.tab); 
    } 
} 
} 

/탭/탭. component.ts

namespace MainApp { 
const mainApp = angular.module("mainApp"); 

class TabsComponent implements ng.IComponentOptions{ 
    public templateUrl: string | ng.Injectable<(...args: any[]) => string>; 
    public controller: any; 
    public controllerAs: string; 
    public bindings: any; 
    public transclude: boolean; 

    constructor() { 
     this.templateUrl = ["rootUrl", (rootUrl) => rootUrl + "app/uitrijregelingBerekening/tabs/tabs.html"]; 
     this.controller = TabsController; 
     this.bindings = { 
      selected:"@", 
     }; 
     this.transclude = true; 
    } 
} 

mainApp.component("tabs", new TabsComponent()); 

} 

/tabs/tabs.controller.ts

namespace MainApp { 
export interface ITabsBindings { 
    selected: number; 
} 

export class TabsController implements ITabsBindings { 
    public selected: number; 
    public tabs: Array<any>; 

    private scope: any; 

    static $inject = ["$scope"]; 
    constructor($scope: ng.IScope) { 
     this.scope = $scope; 

    } 

    public $onInit() { 
     console.log("$onInit"); 
     this.tabs = new Array<any>(); 
    } 

    public addTab(tab: any) { 
     console.log("addTab"); 

     this.tabs.push(tab); 
    } 

    public selectTab(index: number) { 
     for (var i = 0; i < this.tabs.length; i++) { 
      this.tabs[i].selected = false; 
     } 
      this.tabs[index].selected = true; 
    } 

    public $postLink() { 
     console.log("$postLink. nr of tabs added: " + this.tabs.length); 

     this.selectTab(this.selected); 
    } 

} 
} 

템플릿이 동일합니다.

지금 콘솔 출력은 다음과 같습니다

  • $의 onInit
  • $ POSTLINK. 탭의 NR 추가 : 0
  • angular.js : 13920 형식 오류를 : 정의되지 않은
  • addTab의 '선택'설정할 수 없습니다 속성을
  • addTab
  • addTab

내가 여기서 뭔가를 놓치고 있습니까?

답변

0

글쎄, 지금 다른 접근 방식을 사용하고 있습니다. 하나의 컨트롤러에 배열로 밀어 넣기 전에. 이제 두 개의 구성 요소와 컨트롤러가 있습니다.

Typescript 문서에서이 문제가 발생했습니다.

/** 
    * Called after this controller's element and its children have been linked. Similar to the post-link function this 
    * hook can be used to set up DOM event handlers and do direct DOM manipulation. Note that child elements that contain 
    * templateUrl directives will not have been compiled and linked since they are waiting for their template to load 
    * asynchronously and their own compilation and linking has been suspended until that occurs. This hook can be considered 
    * analogous to the ngAfterViewInit and ngAfterContentInit hooks in Angular 2. Since the compilation process is rather 
    * different in Angular 1 there is no direct mapping and care should be taken when upgrading. 
    */ 
    $postLink?(): void; 

Note that child elements that contain templateUrl directives will not have been compiled and linked since they are waiting for their template to load asynchronously and their own compilation and linking has been suspended until that occurs.

대신 require을 사용하는 당신은 어쩌면 아이들에게 tabs 배열을 결합해야한다.

+0

자바 스크립트 코드에서는 2 개의 구성 요소와 컨트롤러도 사용하고 있습니다. 설정은 기본적으로 동일합니다. 탭에서 맞춤 콘텐츠를 코드화 할 수 있기를 원하기 때문에 require를 사용하고 있습니다. 그러나 templateUrl이 비동기 적으로로드되는 자식 요소에 대한 설명은 여기에 대한 답변입니다! 실제로, 리터럴 템플릿으로 전환하면 작동합니다! – Stif

1

@ kuhnroyal 님의 답변이 여기에 맞습니다. 하지만 같은 문제가있는 다른 사람들에게 유용 할 수 있기 때문에 후속 조치를 게시하고 싶습니다.필자는 별도의 파일 (유지 관리 기능이 향상됨)로 템플릿 작업을 할 수있는 솔루션을 찾았지만 템플릿 속성을 사용하여 postLink 이벤트의 올바른 순서를 보장합니다.

이제는 각도의 객체 인 $templateCache으로 작업합니다. 열쇠는 각 응용 프로그램이 시작될 때 모든 템플릿을 미리로드하는 것입니다. 그런 다음 $ templateCache.get 메소드를 사용하여 구성 요소의 template-property를 채 웁니다. 이 post은 저 해결책에 저를지도했다.