agularjs怎么说来指令克隆范围 [英] agularjs how to say to a directive to clone scope

查看:230
本文介绍了agularjs怎么说来指令克隆范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个小提琴,不能使这项工作。我认为,原因在于使用自定义指令的编辑就地份额范围两个李元素。
该解决方案将是说的指令来创建父绑定范围的副本 - 可以帮助transclude

  angular.module('BLA',[])
    .directive('editInPlace',['$解析,$编译,函数($解析,$编译){
    返回{
        限制:'A',
        适用范围:真,
        链接:功能(范围,元素,attribs){
            VAR inputStart ='<输入风格=边界:2纯黑NAME =inPlaceInput的风格=显示:无VALUE =;
            VAR inputEnd ='>';            scope.editModeAccessor ​​= $解析(attribs.editInPlace);
            scope.modelAccessor ​​= $解析(attribs.ngBind);            范围。$腕表(attribs.editInPlace,功能(为newValue,属性oldValue){
                如果(newValue)以{
                    console.debug(点击);
                    console.debug(值:+ scope.modelAccessor(范围));
                    VAR inputHtml = inputStart + scope.modelAccessor(范围)+ inputEnd;
                    element.after(inputHtml);
                    jQuery的(元素).hide();
                    scope.inputElement =的jQuery(输入[名称= inPlaceInput]);
                    scope.inputElement.show();
                    scope.inputElement.focus();
                    scope.inputElement.bind(模糊,函数(){
                        模糊();
                    });
                }其他{
                    模糊();
                }
            });            功能模糊(){
                console.debug(模糊次要);
                如果(scope.inputElement){
                    console.debug(模糊发现二次inputElement);
                    VAR值= scope.inputElement.val();
                    console.debug(输入值:+值);
                    scope.inputElement.remove();
                    jQuery的(元素).show();
                    scope.editModeAccessor.assign(范围,FALSE);
                    scope.modelAccessor.assign(范围值);
                }
            }
        }
    }
                            }]);功能ContactsCtrl($范围,$超时){
    $ scope.contacts = {[编号:'+ 25480989333,名称:'沙龙'},{号码:+ 42079872232,名称:''}];
    $ scope.editMode = FALSE;
    VAR editedId;
    $ scope.edit =功能(ID){
        $ scope.editMode =真;
        jQuery的(#+ id)的.hide();
        editedId = ID;
        // TODO显示删除按钮
    }
    $范围。$表(编辑模式,功能(为newValue,属性oldValue){
        如果(为newValue&安培;!&安培; editedId){
            jQuery的(#+ editedId).show();
        }
    });
}
< D​​IV NG-应用=喇嘛>
< D​​IV NG控制器=ContactsCtrl>
< H4>联系和LT; / H4>
< UL>
    <李NG重复=中的联系人联系>
        <跨度编辑就地=编辑模式NG绑定=contact.number>< / SPAN>
        <跨度编辑就地=编辑模式NG绑定=contact.name>< / SPAN>
        <跨度ID ={{$指数}}NG点击=编辑($指数)>< I类=图标编辑> CLICKtoEDIT< / I>< / SPAN>
    < /李>
< / UL>
< / DIV>< / DIV>


解决方案

我想克隆的范围不是最好的解决方案。

在创造角指令,你应该封装全部的指令范围内的功能。你也应该避免在当你不必混合jQuery的。大部分的时间(如在这种情况下)你只是引入不必要的复杂性。最后,类是控制显示器的最佳途径,而不是一个元素上的风格属性。

我参加了一个更角的方式重写你的指令的自由 - 没有jQuery的。正如你可以看到更新的的jsfiddle ,它更简单,更清洁。此外,它的作品!

该指令可以很容易地修改,添加大量的额外真棒功能。

  app.directive('editInPlace',函数(){
  返回{
    限制:'E',
    适用范围:{值:'='},
    模板:'<跨度NG点击=编辑()NG绑定=值>< / SPAN><输入NG模型=值>< /输入>,
    链接:功能($范围,元素,ATTRS){
      //让我们对输入元素的引用,因为我们将要引用它。
      变种inputElement = angular.element(element.children()[1]);      //这个指令应该有一组类,所以我们可以样式。
      element.addClass(编辑就地');      //起初,我们并没有进行编辑。
      $ scope.editing = FALSE;      // NG单击处理程序来激活编辑就地
      $ scope.edit =功能(){
        $ scope.editing = TRUE;        //我们通过这个指令本身的一类控制显示。见CSS。
        element.addClass(激活);        //我们必须关注的元素。
        //`angular.element()`提供了一个可链接的阵列,像jQuery这样访问本地DOM功能,
        //我们必须引用的第一个元素的数组中为止。
        inputElement [0]。重点();
      };      //当我们离开的投入,我们就大功告成了编辑。
      inputElement.prop('的onblur',函数(){
        $ scope.editing = FALSE;
        element.removeClass(激活);
      });
   }
};

});

I have this fiddle, and can not make this work. I believe that the reason resides in that two li elements with a custom directive edit-in-place share scope. The solution would be to say to the directive to create a copy of the scope that binds on the parent - can transclude help?

angular.module('bla', [])
    .directive('editInPlace', ['$parse','$compile', function($parse, $compile) {
    return {
        restrict: 'A',
        scope: true,
        link: function (scope, element, attribs) {
            var inputStart = '<input style="border: 2 solid black" name="inPlaceInput" style="display:none" value="';
            var inputEnd = '">';

            scope.editModeAccessor = $parse(attribs.editInPlace);
            scope.modelAccessor = $parse(attribs.ngBind);

            scope.$watch(attribs.editInPlace, function(newValue, oldValue){
                if (newValue){
                    console.debug("click");
                    console.debug("value: " + scope.modelAccessor(scope));
                    var inputHtml = inputStart + scope.modelAccessor(scope) + inputEnd;
                    element.after(inputHtml);
                    jQuery(element).hide();
                    scope.inputElement = jQuery("input[name=inPlaceInput]");
                    scope.inputElement.show();
                    scope.inputElement.focus();
                    scope.inputElement.bind("blur", function() {
                        blur();
                    });
                } else {
                    blur();
                }
            });

            function blur(){
                console.debug("blur secondary");
                if (scope.inputElement){
                    console.debug("blur secondary inputElement found");
                    var value = scope.inputElement.val();
                    console.debug("input value: "+ value);
                    scope.inputElement.remove();
                    jQuery(element).show();
                    scope.editModeAccessor.assign(scope, false);
                    scope.modelAccessor.assign(scope, value);
                }
            }
        }
    }
                            }]);

function ContactsCtrl($scope, $timeout){
    $scope.contacts = [{number:'+25480989333', name:'sharon'},{number:'+42079872232', name:''}];
    $scope.editMode = false;
    var editedId;
    $scope.edit = function(id){
        $scope.editMode = true;
        jQuery("#"+id).hide();
        editedId = id;
        //TODO show delete button
    }
    $scope.$watch('editMode', function(newValue, oldValue){
        if (!newValue && editedId){
            jQuery("#"+editedId).show();
        }
    });
}


<div ng-app="bla">
<div ng-controller="ContactsCtrl">
<h4>Contacts</h4>
<ul>
    <li ng-repeat="contact in contacts">
        <span edit-in-place="editMode" ng-bind="contact.number"></span>
        <span edit-in-place="editMode" ng-bind="contact.name"></span>
        <span id="{{$index}}" ng-click="edit($index)"><i class="icon-edit">CLICKtoEDIT</i></span>
    </li>
</ul>
</div></div>

解决方案

I think cloning the scope is not the best solution.

When creating a directive in angular, you should encapsulate all the functionality within the directive. You should also avoid mixing jQuery in when you don't have to. Most of the time (as in this case) you're just introducing unnecessary complexity. Lastly, classes are the best way of controlling display, rather than the style attribute on an element.

I took the liberty of rewriting your directive in a more "angular" way - with no jQuery. As you can see from the updated jsFiddle, it is simpler and cleaner. Also, it works!

This directive can be easily modified to add lots of additional awesome functionality.

app.directive( 'editInPlace', function() {
  return {
    restrict: 'E',
    scope: { value: '=' },
    template: '<span ng-click="edit()" ng-bind="value"></span><input ng-model="value"></input>',
    link: function ( $scope, element, attrs ) {
      // Let's get a reference to the input element, as we'll want to reference it.
      var inputElement = angular.element( element.children()[1] );

      // This directive should have a set class so we can style it.
      element.addClass( 'edit-in-place' );

      // Initially, we're not editing.
      $scope.editing = false;

      // ng-click handler to activate edit-in-place
      $scope.edit = function () {
        $scope.editing = true;

        // We control display through a class on the directive itself. See the CSS.
        element.addClass( 'active' );

        // And we must focus the element. 
        // `angular.element()` provides a chainable array, like jQuery so to access a native DOM function, 
        // we have to reference the first element in the array.
        inputElement[0].focus();
      };

      // When we leave the input, we're done editing.
      inputElement.prop( 'onblur', function() {
        $scope.editing = false;
        element.removeClass( 'active' );
      });
   }
};

});

这篇关于agularjs怎么说来指令克隆范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆