繁体   English   中英

Angular指令模板输入不会更新指令范围

[英]Angular directive template input doesn't update directive scope

我有一个带有隔离范围的自定义指令,并且在它的link函数中,我设置了一些其他范围变量,例如:

templateUrl:"chat.html",
scope:{},
link: function (scope, element, attrs) {
            scope.chat;
            scope.send_txt="";
            scope.use_enter = false;
            scope.other;

在我的chat.html我有一个输入元素

....
...
<textarea ng-model="send_txt" class="form-control" placeholder="Message..." aria-describedby="basic-addon1" style="border:2px solid #0079BE; border-radius:5px;margin-bottom:5px;"></textarea>
...

通常,当我在链接中设置scope.send_txt ,该值会正确反映在textarea中,但是一旦我在textarea中键入内容, scope.send_txt变量就会立即停止更新,就好像textarea现在拥有自己的作用域一样。 任何想法可能是什么问题?

编辑:

指示:

'use strict';

angular.module('chatApp')
  .directive('chatpane', [
    '$http',
    'socket',
    'message',
    '$mdDialog',
    '$mdMedia',
    function ($http,socket,message,$mdDialog,$mdMedia) {
      return {
        templateUrl: 'app/dashboard/message/chatpane/chatpane.html',
        restrict: 'E',
        scope:{
            thread : "=thread",
            owner : "=owner",
        },
        link: function (scope, element, attrs) {
          /*console.log("chat: ",nv, " : ",ov);*/
            scope.chat;
          scope.send_txt="";
            scope.use_enter = false;
            scope.other;

            scope.$watch("thread",function(nv,ov,scope){
                if(nv){
                    $http.get('api/messages/threads/'+nv._id+'/0').then(function(d){
                                    scope.chat = d.data;
                                    scope.other = (scope.owner!=scope.thread.owner._id)?scope.thread.owner._id:scope.thread.recipient._id;
                                    //mark thread read
                              message.markThreadRead(scope.thread._id);
                                })
                }
            },true);

          scope.$watch("send_txt",function(nv,ov,scope){
            console.log("chat: ",nv, " : ",ov);
          },true);

            scope.$watch('chat', function(newValue, oldValue, scope) {
            if(element.find('.msg_inbox_msgs').length>0){
              element.find('.msg_inbox_msgs').stop(true,true).animate({scrollTop:(element.find('.msg_inbox_msgs')[0].scrollHeight+(element.find('.msg_inbox_msgs>div').length*20))+'px'}, 1000);
            }
            });

            scope.post = function(txt){
                var tmp = txt || scope.send_txt;
                scope.send_txt = "";
                console.log("Posting: ",scope.send_txt);
            if(tmp && _.trim(tmp)!=""){
              $http.post('api/messages',{message:tmp, owner:scope.owner, recipient:scope.other, parent: scope.thread._id}).then(function(d){
                //scope.chat.push(d.data);
                //console.log("Response: ",d);
                //console.log("chat: ",scope.chat);
              });
            }else{
              console.log("Posting: ",scope.send_txt);
            }
            }

          scope.acceptReferralRequest = function() {
            $http.post('api/messages/acceptReferralRequest/'+scope.thread._id).then(function(d){
              scope.thread.status = "accepted";
                });
          }
          scope.ignoreReferralRequest = function() {
            $http.post('api/messages/ignoreReferralRequest/'+scope.thread._id).then(function(d){
              scope.thread.status = "ignored";
                });
          }

            element.bind("keydown keypress", function (event) {
                if(event.which === 13 && scope.use_enter) {
                    scope.post();
                    event.preventDefault();
                }
            });

            scope.refer = function(ev){
              var my_connections = [];
              $http.get('api/users/get-all-connections').then(function(d){
                for(var i in d.data){
                  var ii = _.findIndex(my_connections,{'_id':d.data[i]._id});
                  if(ii!=-1){
                    if(my_connections[ii].relation.indexOf(d.data[i].relation) == -1){
                      my_connections[ii].relation = my_connections[ii].relation +", "+d.data[i].relation;
                    }
                  }else{
                    my_connections.push(d.data[i]);
                  }
                }

                //show popup
                var useFullScreen = ($mdMedia('sm') || $mdMedia('xs'));
                $mdDialog.show({
                  controller: function(scope,$mdDialog){
                    scope.connections = my_connections;
                    scope.heading = "Refer";
                    scope.isAuthorized = true;
                    scope.cancel = function(){
                      $mdDialog.cancel();
                    };
                    scope.hide =  function(user_url){
                      $mdDialog.hide(user_url);
                    }
                  },
                  templateUrl: 'app/dashboard/message/chatpane/refer.html',
                  parent: angular.element(document.body),
                  targetEvent: ev,
                  clickOutsideToClose: true,
                  fullscreen: useFullScreen
                })
                .then(function(user_url) {
                  if(scope.send_txt && scope.send_txt!=""){
                    scope.send_txt += " #"+user_url+" ";
                  }else{
                    scope.send_txt = "I would like to recommend #"+user_url+" ";
                  }
                }, function() {
                  scope.status = 'You cancelled the dialog.';
                })
              });

            };



            var handleSelf = function(d){
                if((d.parent == scope.thread._id) && scope.owner==d.owner._id){
                    scope.chat.push(d);
                }
                //console.log("socket self: ",d);
           };
            socket.socket.removeListener('message:posted',handleSelf);
            socket.socket.on('message:posted',handleSelf);

            var handleRemote = function(d){
                if((d.parent == scope.thread._id) && scope.owner==d.recipient._id){
                    scope.chat.push(d);
                }
                //console.log("socket remote: ",d);
           };
            socket.socket.removeListener('message:unread',handleRemote);
            socket.socket.on('message:unread',handleRemote);
        }
      };
    }]);

模板:

{{send_txt}}<div class="msg_inbox_cont" flex="column" flex layout-align="start stretch" ng-if="thread.group!='ask_referral'">
    <div class="msg_inbox_head" flex ng-if="thread.title">
        <div class="msg_topic_img col-sm-1 col-xs-3">
            <img ng-src="api/images/{{msg.currentThread.owner.profile_pic || 'default.png' }}" alt="" width="30"/>
        </div>
        <div class="msg_topic_header col-sm-10 col-xs-9">
            {{ thread.title}}
        </div>
        <div class="msg_topic_desc col-sm-10 col-xs-9">
            {{ thread.message | limitTo:20 }}
        </div>
    </div>
    <div class="msg_inbox_msgs" flex>
        <div ng-class="ch.owner._id == owner ? 'msg_inbox_msg mine' : 'msg_inbox_msg other'" ng-repeat="(key, ch) in chat">
            {{ch.message}}
        </div>
    </div>
    <div class="msg_inbox_input" flex>
        <div class="input-group">
            <textarea ng-model="send_txt" class="form-control" placeholder="Message..." aria-describedby="basic-addon1" style="border:2px solid #0079BE; border-radius:5px;margin-bottom:5px;"></textarea>
        </div>
        <span><input type="checkbox" ng-model="use_enter" style="vertical-align: text-top;" /> Submit on enter</span>
        <input type="button" ng-if='send_txt' class="pull-right btn btn-default btn-primary" ng-click="post()" value="Send"/>
        <input type="button" ng-if='!send_txt' class="pull-right btn btn-default btn-disabled" disabled value="Send"/>
    </div>
</div>


<!-- Ask Referral -->
<div class="msg_inbox_cont" flex="column" flex layout-align="start stretch" ng-if="thread.group=='ask_referral'">
    <div class="msg_inbox_head" flex ng-if="thread.owner._id!=owner">
        <div class="msg_topic_img col-sm-1 col-xs-3">
            <img ng-src="api/images/{{thread.owner.profile_pic || 'default.png' }}" alt="" width="30"/>
        </div>
        <div class="msg_topic_header col-sm-10 col-xs-9">
            {{ thread.owner.name }}
        </div>
        <div class="msg_topic_desc col-sm-10 col-xs-9">
            has asked for a referral
        </div>
    </div>
    <div class="msg_inbox_head" flex ng-if="thread.owner._id==owner">
        <div class="msg_topic_img col-sm-1 col-xs-3">
            <img ng-src="api/images/{{thread.owner.profile_pic || 'default.png' }}" alt="" width="30"/>
        </div>
        <div class="msg_topic_header col-sm-10 col-xs-9">
            You
        </div>
        <div class="msg_topic_desc col-sm-10 col-xs-9">
            have asked for a referral
        </div>
    </div>
    <!-- accepted -->
    <div class="msg_inbox_msgs" flex ng-if="thread.status=='accepted'">
        <div ng-class="ch.owner._id == owner ? 'msg_inbox_msg mine' : 'msg_inbox_msg other'" ng-repeat="(key, ch) in chat">
            {{ch.message}}
        </div>
    </div>
    <!-- accepted -->
    <!-- available / pending acceptance -->
    <div class="msg_inbox_msgs" flex ng-if="thread.status=='available'">
        <div ng-class="ch.owner._id == owner ? 'msg_inbox_msg mine' : 'msg_inbox_msg other'" ng-repeat="(key, ch) in chat">
            {{ch.message}}
        </div>
        <div style="clear:both;" ng-if="thread.owner._id!=owner">
          <input style="margin:10px;" type="button" class="pull-left btn btn-primary" value="Accept" ng-click="acceptReferralRequest()"/>
          <input style="margin:10px;" type="button" class="pull-left btn btn-warning" value="Ignore" ng-click="ignoreReferralRequest()"/>
        </div>
    </div>
    <!-- available / pending acceptance -->
    <!-- available / pending acceptance -->
    <div class="msg_inbox_msgs" flex ng-if="thread.status=='ignored'">
        <div ng-class="ch.owner._id == owner ? 'msg_inbox_msg mine' : 'msg_inbox_msg other'" ng-repeat="(key, ch) in chat">
            {{ch.message}}
        </div>
        <div style="clear:both;text-align:center;">
          <span style="color:#5e5e5e;font-weight:bold;"><small><em>- Request has been ignored -</em></small></span>
        </div>
    </div>
    <!-- available / pending acceptance -->
    <div class="msg_inbox_input" flex ng-if="thread.status=='accepted'">
        <div class="input-group">
            <textarea ng-model="send_txt" class="form-control" placeholder="Message..." aria-describedby="basic-addon1" style="border:2px solid #0079BE; border-radius:5px;margin-bottom:5px;"></textarea>
        </div>
        <span><input type="checkbox" ng-model="use_enter" style="vertical-align: text-top;" /> Submit on enter</span>
        <input type="button" ng-if='send_txt' class="pull-right btn btn-default btn-primary" ng-click="post(send_txt)" value="Send"/>
        <input type="button" ng-if='!send_txt' class="pull-right btn btn-default btn-disabled" disabled value="Send"/>
        <input type="button" ng-if='thread.owner._id!=owner' class="pull-right btn btn-default btn-primary" ng-click="refer($event)" value="Refer"/>{{send_txt}}
    </div>
</div>
<!-- Ask Referral -->

您应该始终有一个. 随着ng-model或奇怪的事情可能会发生,因为可能会引入新的范围...

https://github.com/angular/angular.js/wiki/Understanding-Scopes

按照规范中的规定:

首先, ngModel will try to bind to the property given by evaluating the expression on the current scope. If the property doesn't already exist on this scope, it will be created implicitly and added to the scope. ngModel will try to bind to the property given by evaluating the expression on the current scope. If the property doesn't already exist on this scope, it will be created implicitly and added to the scope.

第二: By default, ngModel watches the model by reference, not value. This is important to know when binding inputs to models that are objects (eg Date) or collections (eg arrays). If only properties of the object or collection change, ngModel will not be notified and so the input will not be re-rendered. By default, ngModel watches the model by reference, not value. This is important to know when binding inputs to models that are objects (eg Date) or collections (eg arrays). If only properties of the object or collection change, ngModel will not be notified and so the input will not be re-rendered.

因此,如果您直接引用,您的引用可能会“丢失”,而这不会发生. ...

尝试:

templateUrl:"chat.html",
scope:{},
link: function (scope, element, attrs) {
  scope.info = {
    send_txt: ""
  };

<textarea ng-model="info.send_txt" class="form-control" placeholder="Message..." 
    aria-describedby="basic-addon1" style="border:2px solid #0079BE; 
    border-radius:5px;margin-bottom:5px;"></textarea>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM