angularjs 中控制器和指令之间的通信

Communication between Controller and Directive in angularjs

本文关键字:之间 通信 指令 控制器 angularjs      更新时间:2023-09-26

我正在尝试使用AngularJS创建一个小应用程序,该应用程序分别由用户和用户发布的问题组成。

我试图在单击特定用户时显示问题。

到目前为止,我已经创建了以下代码:

索引.html

  <div class="container" ng-controller="issueContainer as issueTrack">
      <div class="leftContainer" ng-controller="issueForm as issueformCtrl">
          <issue-form></issue-form>
          <user-issues ng-repeat="issue in user.issues"></user-issues>    
      </div>
      <div class="rightContainer" ng-controller="userForm as userformCtrl">
          <form name="userform" ng-submit="userform.$valid && userformCtrl.addUsers()">
              <div class="form-group">
                <label for="addUser">Username</label>
                <input type="text" id="addUser" ng-model="userformCtrl.name" class="form-control" placeholder="Username">
              </div>
              <div class="form-group">
                <input type="submit" class="btn btn-primary" value="Submit" />
              </div>
          </form>
          <h3 class="usersTitle">Users</h3>
          <div class="users" ng-show="issueTrack.users.length">
              <div ng-repeat="user in issueTrack.users track by $index" value="{{user.username}}" ng-click="userformCtrl.userclickCtrl(user.username)">
                  {{user.username}}
              </div>
          </div>
      </div>
  </div>

应用.js

(function(){
var app = angular.module("Issuetracker",[]);
var users=[];
if (localStorage.getItem('users')!==null){
    users = JSON.parse(localStorage.getItem("users"));
    console.log(users);
}
app.controller("issueContainer", function(){
    var issuetrack = this;
    this.users = users;
});
app.controller("userForm", function(){
    this.addUsers = function(){
        users.push({'username':this.name, 'issues':[]});
        this.name='';
        console.log(users);
        localStorage.setItem("users", JSON.stringify(users));
    };      
    this.userclickCtrl= function(data){
        var allUsers = JSON.parse(localStorage.getItem("users"));
        for(var i=0;i< allUsers.length;i++){
            if(allUsers[i].username == data){
                var userData = allUsers[i];
                break;
            }
        }
    };
});
app.controller("issueForm", function(){
    this.issue={};
    this.addIssues = function(){
        console.log(this.issue);
        var allUsers = JSON.parse(localStorage.getItem("users"));
        for(var i=0;i< allUsers.length;i++){
            if(allUsers[i].username == this.issue.User){
                allUsers[i].issues.push(this.issue);
                break;
            }
        }            
        this.issue={};
        localStorage.setItem("users", JSON.stringify(allUsers));
    };                
});
app.directive("userIssues", function(){
   return{
        restrict: 'E',
        templateUrl: 'userissues.html'
   }  
});
app.directive("issueForm", function(){
   return{
        restrict: 'E',
        templateUrl: 'issueform.html' 
   }  
});
})()

用户问题.html

<div class="issues">
    <div ng-repeat="issue in user.issues">
        <h3>{{issue.Summary}}<span class="label label-primary" style="margin-left:2%">{{issue.Type}}</span></h3>
        <p>{{issue.Description}}</p>
    </div>
</div>

每当单击任何用户时,都会调用userclickCtrl函数,其中我从localStrorage获取用户对象并希望将其传递给模板的userissues指令。

任何线索将不胜感激!!

不确定您使用localStorage做什么,用于在控制器和指令之间共享数据? 为什么不直接使用Windows.users..但这也是不好的做法。

我能想到两种方法可以使控制器指令通信成为可能。

1.使用事件发布/订阅($on$broadcast$emit

在控制器中,使用 $scope.$broadcast('eventName',eventData) 将消息发送到其所有子作用域,在指令中,使用 $scope.$on('eventName',callback) 侦听该消息。该指令还可以使用 scope.$emit('eventName',eventData) 向控制器发送消息,请进行一些谷歌搜索或参考官方文档以获取更多详细信息。

如果你能想办法获取指令作用域的引用,直接在指令作用域上使用广播,会更有效,因为事件不会被广播到不相关的作用域。

此外,出于效率考虑,当您在指令中使用$emit时,控制器中的$on回调应包含 event.defaultPrevented = true; ,以阻止事件传播到不相关的更高类作用域。

2.通过指令属性将控制器中对象的引用(我们可以将对象称为处理程序/委托/等不太确定)传递到指令中。

我不确定这是否是一种好的做法,但这是我经常使用的有效做法。

例如

该指令:

.js:

  app.directive('userIssues', function () {
      return {
          restrict: 'E',
          templateUrl: 'templates/user-issues.html',
          scope: {
              delegate: '='
          },
          link: function (scope, element, attr) {
              scope.issues = [];
              scope.delegate.addIssue = function (issue) {
                  scope.issues.push(issue);
                  console.log("An issue is added to the directive !!");
              };
              scope.issueClicked = function (id) {
                  scope.delegate.issueClicked(id);
              }  
          }
      }
  });

.html:

 <div>
     {{issues}} //I will change when notified from controller
     <button ng-click="issueClicked(123)">
         click me to notify controller
     </button>
 </div>

控制器:

.js:

app.controller('myController', function ($scope, $timeout) {
    $scope.issueDirectiveDelegate = {
        issueClicked: function (id) {
            console.log("received message from the directive that issue with id ", id, 'is clicked');
        }
    };
    $timeout(function(){
        getMoreIssues().then(function (issue) {
            $scope.issueDirectiveDelegate.addIssue(issue);
        });
    },1000);
});

.html:

<div> <div>blahblah</div>
   <user-issues delegate="issueDirectiveDelegate"></user-issues>
</div>

不知道我是否遇到了你的问题,但也许这是一个可能的解决方案。

您可以通过以下方式将问题作为参数传递给您的指令:

app.directive("userIssues", function(){

返回{

    restrict: 'E',
    scope: { issue: '=' },
    templateUrl: 'userissues.html'


}});

你可以像这样使用它:

<user-issues ng-repeat="issue in issues" issue="issue"></user-issues>

试试这个小提琴的例子

希望这是你需要的

我很高兴@KevinWang和@Rick帮助我找到了我正在寻找的答案。除此之外,我还发现了一个很棒的教程,关于理解指令中的范围,它解释并补充了@Rick的答案。我在这里分享链接以详细说明。

http://www.undefinednull.com/2014/02/11/mastering-the-scope-of-a-directive-in-angularjs/