如何使用Angular的ng-model与jQuery UI的滑块?

时间:2015-08-20 14:54:33

标签: javascript jquery angularjs jquery-ui

我在我的一个页面上使用jQuery UI的滑块,我想使用ng-model将值绑定到我的控制器。滑块渲染如下:

<div id="speakerSlider" class="ui-slider ui-slider-horizontal ui-widget ui-widget-content ui-corner-all ui-slider-pips" aria-disabled="false">
    <a class="ui-slider-handle ui-state-default ui-corner-all" href="#" style="left: 40%;"></a>
    <span class="ui-slider-pip ui-slider-pip-first ui-slider-pip-label ui-slider-pip-0 ui-slider-pip-selected-initial" style="left: 0%">
     <span class="ui-slider-line"></span><span class="ui-slider-label" data-value="0">0</span>
    </span>
    <span class="ui-slider-pip ui-slider-pip-label ui-slider-pip-1" style="left: 20.0000%">
      <span class="ui-slider-line"></span><span class="ui-slider-label" data-value="1">1</span>
    </span>
    <span class="ui-slider-pip ui-slider-pip-label ui-slider-pip-2 ui-slider-pip-selected" style="left: 40.0000%">
      <span class="ui-slider-line"></span><span class="ui-slider-label" data-value="2">2</span>
    </span>
    <span class="ui-slider-pip ui-slider-pip-label ui-slider-pip-3" style="left: 60.0000%">
      <span class="ui-slider-line"></span><span class="ui-slider-label" data-value="3">3</span>
    </span>
    <span class="ui-slider-pip ui-slider-pip-label ui-slider-pip-4" style="left: 80.0000%">
      <span class="ui-slider-line"></span><span class="ui-slider-label" data-value="4">4</span>
    </span>
    <span class="ui-slider-pip ui-slider-pip-last ui-slider-pip-label ui-slider-pip-5" style="left: 100%">
      <span class="ui-slider-line"></span>
      <span class="ui-slider-label" data-value="5">5</span>
    </span>
</div>

根据angulars documentation ng-model,只能在inputselecttextArea元素上使用。由于这些都不是滑块的一部分,我不能使用ng-model?我的另一个想法是创建一个隐藏的输入,并在每次滑块更新时插入值。这是我最好的选择,还是有更好的解决方法?

3 个答案:

答案 0 :(得分:2)

ng-model不仅适用于原生表单元素 - 文档还在第一段中提到“自定义表单控件”。

这是一个为angular提供jQueryUI滑块指令的库: https://github.com/angular-ui/ui-slider

演示页:http://angular-ui.github.io/ui-slider/demo/demo.html

我推荐来自ng-conf 2014的演讲Using ngModelController to Make Sexy Custom Components来解释ngModelController如何为自定义表单元素工作。

答案 1 :(得分:1)

要将ngModel与自定义控件一起使用:创建自定义指令,获取ngModelController引用,并使用必要的方法/属性($render$setViewValue$viewValue )更新滑块/模型。

angularjs example修改

&#13;
&#13;
var app = angular.module("app",[]);

app.directive('slider', [function() {
  return {
    restrict: 'A', // only activate on element attribute
    require: '?ngModel', // get a hold of NgModelController
    link: function(scope, element, attrs, ngModel) {
      if (!ngModel) return; // do nothing if no ng-model

      // Initialize slider and setup change event to enable updating the value
      jQuery(element).slider({
        'change': function() {
            scope.$evalAsync(setModelValue);
        }
      });
      
      //Read data from model into custom control
      ngModel.$render = function() {
        jQuery(element).slider("value",ngModel.$viewValue || 0);
      };

      setModelValue();

      // Write data from control to the model
      function setModelValue() {
        var value = jQuery(element).slider("value");
        ngModel.$setViewValue(value);
      }
    }
  };
}]);
&#13;
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
<link rel="stylesheet" href="https://rawgithub.com/simeydotme/jQuery-ui-Slider-Pips/master/dist/jquery-ui-slider-pips.css">

<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://rawgithub.com/simeydotme/jQuery-ui-Slider-Pips/master/dist/jquery-ui-slider-pips.min.js"></script>

<div ng-app="app">
  {{slideval}}
  
<div id="speakerSlider" slider ng-model="slideval" class="ui-slider ui-slider-horizontal ui-widget ui-widget-content ui-corner-all ui-slider-pips" aria-disabled="false">
    <a class="ui-slider-handle ui-state-default ui-corner-all" href="#" style="left: 40%;"></a>
    <span class="ui-slider-pip ui-slider-pip-first ui-slider-pip-label ui-slider-pip-0 ui-slider-pip-selected-initial" style="left: 0%">
     <span class="ui-slider-line"></span><span class="ui-slider-label" data-value="0">0</span>
    </span>
    <span class="ui-slider-pip ui-slider-pip-label ui-slider-pip-1" style="left: 20.0000%">
      <span class="ui-slider-line"></span><span class="ui-slider-label" data-value="1">1</span>
    </span>
    <span class="ui-slider-pip ui-slider-pip-label ui-slider-pip-2 ui-slider-pip-selected" style="left: 40.0000%">
      <span class="ui-slider-line"></span><span class="ui-slider-label" data-value="2">2</span>
    </span>
    <span class="ui-slider-pip ui-slider-pip-label ui-slider-pip-3" style="left: 60.0000%">
      <span class="ui-slider-line"></span><span class="ui-slider-label" data-value="3">3</span>
    </span>
    <span class="ui-slider-pip ui-slider-pip-label ui-slider-pip-4" style="left: 80.0000%">
      <span class="ui-slider-line"></span><span class="ui-slider-label" data-value="4">4</span>
    </span>
    <span class="ui-slider-pip ui-slider-pip-last ui-slider-pip-label ui-slider-pip-5" style="left: 100%">
      <span class="ui-slider-line"></span>
      <span class="ui-slider-label" data-value="5">5</span>
    </span>
</div>
&#13;
&#13;
&#13;

请注意,该演示并未完全使用您自己将该功能挂起的点数。

使用隐藏输入法几乎是一样的,你仍然需要一些事件来跟踪所有事情并更新滑块/模型。

隐藏的输入代码示例

<div ng-controller="myCtrl">
    <div id="speakerSlider">
        <input type="hidden" ng-model="slideval">
        <-- rest of slider code -->
    </div>
</div>

JS

app.controller("myCtrl",["$scope",function($scope){
    $scope.slideval = 0;        

    var slider = jQuery("#speakerSlider");        
    slider.slider({
        change:function(){
            $scope.$evalAsync(function(){
               $scope.slideval = slider.slider("value");
            });
        }
    });

    //This is required so if you do
    //$scope.slideval = 5
    //the slider will be updated
    //otherwise you would have to do slider("value",...) every time
    $scope.$watch('slideval', function(newValue, oldValue) {
       slider.slider("value",newValue);
    });
}]);

虽然你没有指令代码的开销,但还有一些缺点:

  1. 您创建了第二个观察者。已经为隐藏输入的ng模型创建了一个观察者。由于您无权访问它,因此您必须在控制器中设置$scope.$watch以监视任何更改,以便您可以对其进行操作。如果可以访问原始观察者,我不知道这样做的过程。
  2. 不是模块化的,您必须复制/更改每个滑块的代码(或者设置一个构造函数,您可以传入$ scope,但仍然需要在每个控制器中调用它),而使用指令路径您只需要为每个滑块添加slider ng-model="model"
  3. 即可

答案 2 :(得分:0)

您应该能够在示波器上创建变量并将它们绑定到每个滑块。

angular.module('myApp').controller('sliderCtrl', function($scope) {
    $scope.slider1 = 1;
});

<span class="ui-slider-pip ui-slider-pip-last ui-slider-pip-label ui-slider-pip-1" style="left: 100%">
  <span class="ui-slider-line"></span>
  <span class="ui-slider-label" data-value="{{slider1}}">1</span>
</span>

Theres还有一些角度友好的滑块模块:

https://github.com/venturocket/angular-slider

https://github.com/rzajac/angularjs-slider