Angularjs指令:如何处理与复选框指令 [英] Angularjs directive: how to manipulate checkbox with directive

查看:125
本文介绍了Angularjs指令:如何处理与复选框指令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创造一个复选框功能切换开关指令。我试着从GitHub几个常见的解决方案,但没有完成所有的以下内容:

I'm trying to create a functional toggle switch directive for checkboxes. I've tried a few common solutions from github but none do all of the following:


  • 考虑到 NG-真值

  • 正确更新父控制器的范围

  • 正确配合父窗体的验证状态(我的意思是,有一些解决方案在那里,改变值时,窗体保持原始,等等。)

不过,如果我创建一个使用transclusion通过复选框指令,我的所有要求都得到满足。不过,我不能想出一个办法点击我的神奇的拨动开关时要改变我的transcluded复选框输入的状态。

However, if I create a directive that uses transclusion to pass through the checkbox, all my requirements are met. However, I can't figure out a way to change the status of my transcluded checkbox input when my "fancy" toggle switch is clicked.

下面是我的指令的精简版:

Here's a stripped-down version of my directive:

app.directive('toggleSwitch',function(){
  return {
    restrict: 'AE',
    replace: true,
    transclude: true,
    template: '<span class="switch" ng-click="toggleSwitch()"><span class="fancySwitch"></span><span ng-transclude></span></span>',
    link: function(scope, elem){
      scope.toggleSwitch = function(){
        //modify my fancy switch via classes (I can handle this part)

        //How do I modify the status of my checkbox? (this needs to toggle the status of the checkbox - checked or no)

      };
    }
  };
});

编辑:我想出了一个办法,以满足我的目标没有transclusion(见下文)

我已经更新的问题标题,以更好地反映了我最初的挑战,我下面将溶液作为答案。

I've updated the question headline to better reflect my initial challenge and I'm adding a solution below as an answer.

推荐答案

我发现,如果我preserve原始输入和指令适用于它,我就可以利用ngModel控制器来完成我想要什么:

I found that if I preserve the original input and apply the directive to it, I can then utilize the ngModel controller to accomplish what I want:

我prePEND使用我的自定义开关()之前,然后添加一个click事件侦听到它。如果不更换该指令的模板输入,输入仍然是在父窗体的一部分,是家长的范围之内(使我既在元素上访问验证属性,因此,整体的形式)。

I prepend my custom switch using before(), then add a click event listener to it. By not replacing the input in the directive's template, the input is still part of the parent form and is part of the parent's scope (enabling me to access validation properties on both the element, and hence, the form overall).

当点击开关,我可以使用切换复选框状态 $ setViewValue ,我不担心处理 NG-真值,因为这是照顾。 $ setViewValue 将神奇导致父窗体运行验证和改变原始状态,等我也可以做其他事情像输入本身 $使用setDirty() $的validate(),我就无法做到(我能找到),使用transclusion 。此外,没有transclusion,我的指令是在视图精简。

When the switch is clicked, I can toggle the checkbox status using $setViewValue and I don't have to worry about dealing with ng-true-value, as that is taken care of. $setViewValue will "magically" cause the parent form to run validation and change the "pristine" status, etc. I can also do other things to the input itself like $setDirty() and $validate(), which I wouldn't be able to do (that I could find) using transclusion. Also, without transclusion, my directive is leaner on the view.

<input toggle-switch ts-true-label="Affirmative" ts-false-label="Negative" type="checkbox" name="isApproved" ng-model="sampleForm.isApproved" ng-true-value="'Yes'" ng-false-value="'No'">

和则指令:

app.directive('toggleSwitch',function($timeout){
    return {
      restrict: 'AE',
      replace: false,
      require: '?ngModel',
      link: function (scope, elem, attrs, ngModel){

        var switchElem;//the new switch element

        //Hide the checkbox
        elem.css({display: 'none'});

        /**
         * Toggle the switch. This function is called on the click event on the generated toggle switch
         */
        var toggleTheSwitch = function(){
          //toggle the checkbox
          if(ngModel.$viewValue === true){
            ngModel.$setViewValue(false);//note: setting view value sets the value for the view (ie, checks the checkbox, etc, then sets appropriate model view for us, also the form validates for us)
            switchElem.removeClass('checked');
          }
          else{
            ngModel.$setViewValue(true);
            switchElem.addClass('checked');
          }
          //run all checks and set appropriate status for this individual elem
          ngModel.$setDirty();
          ngModel.$setTouched();
          ngModel.$validate();
          ngModel.$render();
        };

        /**
         * Creates and adds the switch html to the dom
         */
        var createSwitch = function(){
          if(switchElem){
            switchElem.remove();
          }
          //Create the toggle switch
          var switchHTML = '';
          switchHTML += '<span class="switch' + (attrs.class ? ' ' + attrs.class : '') + ' ' + (ngModel.$viewValue ? 'checked' : '') +'" >';
          switchHTML +=   '<span class="label checkedLabel">'+(attrs.tsTrueLabel ? attrs.tsTrueLabel: '')+'</span>';
          switchHTML +=   '<span class="label uncheckedLabel">'+(attrs.tsFalseLabel ? attrs.tsFalseLabel: '')+'</span>';
          switchHTML +=   '<small></small>';
          switchHTML += '</span>';

          switchElem = angular.element(switchHTML);//create angular jqlite object
          elem.before(switchElem);//add new stuff before the checkbox
        };


        //After the directive is done loading, we can access ngModel controller
        $timeout(function() {
          //create the switch
          createSwitch();

          //set onclick event
          switchElem.on('click', function(){
            toggleTheSwitch();
          });
        });

      }

    };
  });

有关其他人,随意使用它。你必须自己创建过程的CSS。

For anybody else, feel free to use it. You'll have to create the css yourself, of course.

这篇关于Angularjs指令:如何处理与复选框指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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