我已经得到了以下指令(为了简洁,我已经删除了非重要部分):
我基本上使用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>
,因此不允许我以编程方式设置事件处理程序。
<!-- 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);
}
<div ng-controller="ChatCtrl">
<chat-window chat-model="chatModel" chat-section='lobby'></chat-window>
</div>
出于某种原因,我虽然会操作控制器而不是指令 - 因此使用sendMessage('hi')
代替chat.sendMessage('hi')
解决了问题......