Angularjs指令:如何使用指令操作复选框

时间:2015-01-20 00:13:54

标签: angularjs

我正在尝试为复选框创建一个功能切换开关指令。我已经尝试了一些来自github的常见解决方案,但没有一个完成以下所有操作:

  • 考虑到ng-true-value
  • 正确更新父控制器的范围
  • 与父表单的验证状态正确绑定(我的意思是,有一些解决方案,当更改值时,表单仍然是“原始”等)。

但是,如果我创建一个使用transclusion传递复选框的指令,则满足我的所有要求。但是,当我单击“奇特”切换开关时,我无法想办法改变我的转换复选框输入的状态。

这是我的指令的简化版本:

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)

      };
    }
  };
});

编辑:我找到了一种方法来实现我的目标而不进行翻译(见下文)。

我已更新问题标题以更好地反映我的初步挑战,并在下面添加解决方案作为答案。

1 个答案:

答案 0 :(得分:0)

我发现如果我保留原始输入并将指令应用于它,那么我可以使用ngModel控制器来完成我想要的任务:

我使用before()添加自定义开关,然后向其添加单击事件侦听器。通过不替换指令模板中的输入,输入仍然是父窗体的一部分,并且是父窗口范围的一部分(使我能够访问元素和整个窗体的验证属性)。

单击开关后,我可以使用$setViewValue切换复选框状态,我不必担心处理ng-true-value,因为这样做。 $setViewValue将“神奇地”导致父表单运行验证并更改“原始”状态等。我还可以对输入本身执行其他操作,例如$setDirty()$validate(),我无法做(我能找到)使用翻译。此外,没有翻译,我的指令在视图上更精简。

<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。