Angularjs使用指令对ng-repeat进行双向数据绑定

时间:2014-05-11 14:46:33

标签: angularjs jquery-ui data-binding angularjs-directive angularjs-ng-repeat

我想要实现的目标:在jquery ui事件上触发一个角度js指令,该事件又调用控制器中的一个方法,该方法在一个应该出现在视图中的数组中添加一个值因为双向数据绑定。

什么行不通:在数组中正确添加了值,但视图未更新

HTML

<li id="collection_{{$index+1}}" class="collection" ng-repeat="collection in column | filter:avoidUndefined" ng-controller="collectionController" ng-model="collection">
    <h1 class="collection-title"> {{ collection.title }}</h1>
    <ul class="bookmarks sortable droppable" droppable=".draggable" sortable=".bookmarks.sortable">
        <li class="bookmark" ng-repeat="bookmark in collection.bookmarks">
            <a class="bookmark-link bookmark-{{bookmark.id}}" href="{{bookmark.url}}">{{bookmark.title}}</a>
        </li>
    </ul>
</li>

指令

directives.directive('droppable',function(){
  return {
    link:function(scope,el,attrs){
        el.droppable({
            accept: attrs.droppable,
            drop: function( event, ui ) {            
                var url = $(ui.helper).text();
                scope.addBookmark(null, url, url);
                $(this).removeClass('ui-state-highlight');
            },
...

CONTROLLER

$scope.addBookmark = function (id, title, url){
    if (id == null) {
        ...
    }
    var bookmark = {
        'id': id,
        'title': title,
        'url': url,
        'type': 'bookmark'
    };
    $scope.collection.bookmarks.push(bookmark);
};

$scope.collection.bookmarks已正确更新,但视图保持不变。如果我使用普通按钮直接调用相同的addBookmark函数,则可以正常工作。

2 个答案:

答案 0 :(得分:1)

您忘了在$apply

中包装掉落回调
directives.directive('droppable',function(){
  return {
    link:function(scope,el,attrs){
        el.droppable({
            accept: attrs.droppable,
            drop: function( event, ui ) {            
                scope.$apply(function(scope){
                    var url = $(ui.helper).text();
                    scope.addBookmark(null, url, url);
                    $(this).removeClass('ui-state-highlight');
                });
            },
...

答案 1 :(得分:0)

我的建议是使用$emit而不是直接在你的指令中调用控制器的方法。

指令应该始终是独立的组件,如果在指令内部有一个来自控制器的方法(在指令之外),这将在我的指令和控制器之间创建一个依赖关系,当然这将迫使一个人不能没有对方存在。

如果我必须将设计原则应用于指令,则它将是SOL in SID,单一责任原则。指令应该能够封装和独立工作。

我可能会在我的指令上尝试这个:scope.$emit("UrlChanged", url);

这样的事情:

directives.directive('droppable',function(){
  return {
    link:function(scope,el,attrs){
        el.droppable({
            accept: attrs.droppable,
            drop: function( event, ui ) {            
                    var url = $(ui.helper).text();
                    scope.$emit("UrlChanged", url);
                    $(this).removeClass('ui-state-highlight');

            },

在我的控制器上:

$scope.$on("UrlChanged", function(event, url){
   ... //your has changed.    
});