2013-02-27 17 views
17

AngularJSで遊んで始め、バインディングテクニックを理解しようとしています。はじめに、私は単純な変換電卓(数十から数十まで)を作ろうとしました。それはうまくいったが、私は範囲値を調整する際入力が更新されない同じモデルプロパティに範囲入力と入力の両方に結合しようとしたとき。破壊され、作業フィドルのためAngularJSで範囲と数値を入力する双方向バインド

共通のjavascript:

var myApp = angular.module('myApp', []); 

myApp.controller('CalcCtrl', function ($scope) { 
    var num = 0.0; 
    $scope.qty = new Quantity(12); 
    $scope.num = num; 
}); 

function Quantity(numOfPcs) { 
    var qty = numOfPcs; 
    var dozens = numOfPcs/12; 

    this.__defineGetter__("qty", function() { 
     return qty; 
    }); 

    this.__defineSetter__("qty", function (val) { 
     qty = val; 
     dozens = val/12; 
    }); 

    this.__defineGetter__("dozens", function() { 
     return dozens; 
    }); 

    this.__defineSetter__("dozens", function (val) { 
     dozens = val; 
     qty = val * 12; 
    }); 
} 

BROKEN FIDDLE

HTML:しかし

<div ng-controller="CalcCtrl"> 
    <form> 
     <label for="pcs">Pieces:</label> 
     <input type="number" min="0" ng-model="qty.qty" size="20" id="pcs" 
     /> 
     <input type="range" min="0" max="100" ng-model="qty.qty" /> 
     <br/> 
     <label for="numOfDozens">Dozens</label> 
     <input type="number" min="0" ng-model="qty.dozens" size="20" 
     id="numOfDozens" /> 
    </form> 
</div> 

、結合2つの入力に私は行動を示すjsfiddleを持っています同じモデルのプロパティは、このフィドルで示されているようにうまく動作しているようです:

WORKING FIDDLE

HTML:

<div ng-controller="CalcCtrl"> 
    <form> 
     <label for="pcs">Pieces:</label> 
     <input type="number" min="0" ng-model="qty.qty" size="20" id="pcs" 
     /> 
     <input type="number" min="0" max="100" ng-model="qty.qty" /> 
     <br/> 
     <label for="numOfDozens">Dozens</label> 
     <input type="number" min="0" ng-model="qty.dozens" size="20" 
     id="numOfDozens" /> 
    </form> 
</div> 

AngularJSで単一のモデルプロパティにバインド範囲入力を取得するにはどのように任意のアイデア?ありがとう。

+0

私はタイプ= "範囲" がサポートされているとは思いませんします。https:/ /github.com/angular/angular.js/issues/1189あなた自身の指示を書く必要があるでしょう。 –

答えて

17

問題ここでは、(入力タイプ=「数」は数字のみで動作しながら)入力タイプ=「範囲」番号ストリングとしないで動作するということです。

http://www.w3.org/wiki/HTML/Elements/input/range

レンジ状態は に番号を表す文字列を要素の値を設定するためのコントロールを表します。

あなたはそれが動作するはずqtyセッターにあなたの最初の命令としてval = parseInt(val)を追加する場合:

this.__defineSetter__("qty", function (val) {   
    val = parseInt(val); 
    qty = val; 
    dozens = val/12; 
}); 

はjsfiddlehttp://jsfiddle.net/bmleite/2Pk3M/2/

+14

範囲入力は基本的に数字選択ではありませんか?なぜ彼らは文字列を使用していますか? –

+6

'parseInt(val、10);' –

+1

@ LiiviuTにする必要があります。おそらく後方互換性のために文字列を使用しました。 'type =" range "を実装していない古いブラウザでは、' input'も文字列型の 'value'を持つテキストフィールドとして使用できます。より新しいブラウザでも 'value'を文字列にすることは、ブラウザの互換性のバグを回避します。 –

7

私はこのソリューションは、より汎用的であると思います。

myApp.directive('input', function() { 
return { 
    restrict: 'E', 
    require: '?ngModel', 
    link: function(scope, element, attrs, ngModel) { 
     if ('type' in attrs && attrs.type.toLowerCase() === 'range') { 
      ngModel.$parsers.push(parseFloat); 
     } 
    } 
}; 

});

full explanation

+0

私はこの解決が気に入っています。私は 'parseFloat'を' Number'に置き換えましたが;-) – joeytwiddle

0

あなたはng-model-optionsを使用してそれを解決することができます。私はjsfiddleを変更し、ここでのコードは次のとおりです。

HTML

<div ng-controller="CalcCtrl"> 
    <form> 
     <label for="pcs">Pieces:</label> 
     <input type="number" min="0" ng-model="qty.qty" size="20" id="pcs" ng-model-options="{ getterSetter: true }"/> 
     <input type="range" min="0" max="100" ng-model="qty.qty" ng-model-options="{ getterSetter: true }"/> 
     <br/> 
     <label for="numOfDozens">Dozens</label> 
     <input type="number" min="0" ng-model="qty.dozens" size="20" 
     id="numOfDozens" ng-model-options="{ getterSetter: true }"/> 
    </form> 
</div> 

JS

var myApp = angular.module('myApp', []); 

myApp.controller('CalcCtrl', function ($scope) { 
    var num = 1.0; 
    $scope.qty = { 
    qty:function (val) { 
     return arguments.length ? (num = parseFloat(val)) : num; 
    }, 
    dozens: function (val) { 
      return arguments.length ? (num = val*12) : num/12; 
     } 
    }; 
}); 
関連する問題