AngularJS / Typescript - 带有动态模板加载和事件的指令

时间:2015-09-23 12:21:50

标签: angularjs templates dynamic angularjs-directive typescript

我已经得到了以下指令(为了简洁,我已经删除了非重要部分):

我基本上使用ng-include指令来动态加载我的模板。

指令

module chat.directives {
  "use strict";
  export class ChatWindow implements ng.IDirective {
    public restrict = 'E'
    public static DirectoryName = "chatWindow";
    public scope = {
      chatModel: '=',
      chatSection: '@chatSection'
    }

    public template(element : ng.IAugmentedJQuery, attrs : IChatWindowAtributes) {
      return '<div ng-include="getTemplateUrl()"></div>';
    }

    public link(scope:chat.controllers.IChatScope, element:ng.IAugmentedJQuery, attrs:ng.IAttributes) {

      scope.getTemplateUrl = () => {
        return "/chat/directives/" + scope.chatSection + "-chat-window-template.html";
      }
    }


    public static factory():ng.IDirectiveFactory {
      var directive = () => new ChatWindow();
      directive.$inject = [];
      return directive;
    }
  }

  interface IChatWindowAtributes extends ng.IAttributes {
    chatSection : string;
  }

  angular
    .module('chat')
    .directive(chat.directives.ChatWindow.DirectoryName, chat.directives.ChatWindow.factory());
}

一旦我尝试在其中一个模板中实现事件,就会出现问题,例如ng-click

因为我使用的是ng-include hack,所以element.html()的链接功能会引用<div ng-include="getTemplateUrl()"></div>,因此不允许我以编程方式设置事件处理程序。

HTML模板

<!-- Chat window-->
<div class="col-xs-4 chat-window">
  <aside>
    <div class="panel panel-default">
      <div class="panel-heading">
        <span class="glyphicon glyphicon-list-alt icon"></span>
      </div>
      <div class="chat-output">

      </div>
      <form action="">
        <input id="msgInput" autocomplete="off"/>
        <button ng-click="chat.sendMessage('hi')" stop-event>Send</button>
      </form>
    </div>
  </aside>
</div>

此外,来自ng-click="chat.sendMessage('hi')"模板的任何调用都不会触发我控制器中的相应功能。

控制器实施

module chat.controllers {
  'use strict';

  class ChatCtrl {

    public chatHistory : Array<Common.Services.IMessage> = [];
    public chatSection : string;
    public currentMessage : string;

    // $inject annotation.
    // It provides $injector with information about dependencies to be injected into constructor
    // it is better to have it close to the constructor, because the parameters must match in count and type.
    // See http://docs.angularjs.org/guide/di
    public static $inject = [
      '$scope',
      'UserService',
      'MessageService'
    ];

    // dependencies are injected via AngularJS $injector
    constructor(private $scope: IChatScope, private userService : User.Services.IUserService, private messageService : Common.Services.IMessageService) {
      this.$scope.chatModel = {
        chatHistory: this.chatHistory,
        userService : this.userService,
        messageService: this.messageService,
        storeChatSectionInCtrl : this.storeChatSectionInCtrl,
        subscribeToChatSectionEvents : this.subscribeToChatSectionEvents,
        fetchChatHistory : this.fetchChatHistory
      }
    }

    public storeChatSectionInCtrl(section){
      // Store the section additionally to the directive in the controller
      this.chatSection = section;
    }

    public subscribeToChatSectionEvents(section : string){
      var self = this;

      // Subscribe for the chat section for incoming messages
      this.messageService.addMessageListener(section + "ChatMessage", function(){

      });

      // Subscribe for incoming messages to load the chat history
      this.messageService.addMessageListener(section + "ChatHistory", function(message : ChatHistoryMessage){
        self.chatHistory = message.data.chatHistory;
      });
    }

    // Send a chat message to the server
    public sendMessage(message : string){
      var messageObj = new ChatInputMessage({
        chatSectionPrefix : this.chatSection,
        chatMessageObj : new ChatMessage({
          message : message
        })
      });

      this.messageService.sendMessage(messageObj);
    }

    // Send a request for the chat history to the server
    public fetchChatHistory(section : string){
      var messageObj : ChatHistoryMessage = new ChatHistoryMessage({
       chatSectionPrefix : section,
       chatHistory : null
       });

       // Send a request in order to retrieve the chat history of the given section
       this.messageService.sendMessage(messageObj);
    }
  }

  export interface IChatScope extends ng.IScope {
    getTemplateUrl : () => string;
    chatModel : IChatModel;
    chatSection : string;
  }

  export interface IChatModel {
    chatHistory :  Array<Common.Services.IMessage>;
    userService: User.Services.IUserService;
    messageService : Common.Services.IMessageService;
    storeChatSectionInCtrl : (section : string) => void;
    subscribeToChatSectionEvents: (nameOfEventListener : string) => void;
    fetchChatHistory : (section: string) => void;
  }

  // Message
  export interface IChatMessage {
    message : string;
    creationDate? : string;
    from? : string;
    to? : string;
  }

  export class ChatMessage implements IChatMessage {
    public message : string;
    public creationDate : string;
    public from : string;
    public to : string;

    constructor(message : IChatMessage){
      this.message = message.message;
      this.creationDate = message.creationDate;
      this.from = message.from;
      this.to = message.to;
    }
  };

  // Message Service
  export interface IChatData{
    chatSectionPrefix : string;
    chatMessageObj : IChatMessage;
  }

  export class ChatInputMessage extends Common.Services.ClientMessage<IChatData> {
    static NAME = "ChatMessage";

    constructor (chatData: IChatData) {
      super(chatData.chatSectionPrefix + ChatInputMessage.NAME, chatData);
    }
  }

  // Chat history
  export class ChatHistoryMessage extends Common.Services.ClientMessage<IChatHistory> {
    static NAME = "ChatHistory";

    constructor (chatData: IChatHistory) {
      super(chatData.chatSectionPrefix + ChatHistoryMessage.NAME, chatData);
    }
  }

  export interface IChatHistory{
    chatSectionPrefix : string;
    chatHistory : Array<IChatMessage>;
  }

  /**
  * @ngdoc object
  * @name chat.controller:ChatCtrl
  *
  * @description
  *
  */
  angular
    .module('chat')
    .controller('ChatCtrl', ChatCtrl);
}

HTML

 <div ng-controller="ChatCtrl">
      <chat-window chat-model="chatModel" chat-section='lobby'></chat-window>
    </div>

解决方案

出于某种原因,我虽然会操作控制器而不是指令 - 因此使用sendMessage('hi')代替chat.sendMessage('hi')解决了问题......

0 个答案:

没有答案