私が達成しようとしているのは、+および-ボタンをクリックして入力フィールドの数値を増減できるように、入力フィールドに追加のインターフェースを追加することです。
(本質的に、それはinput [type = number]フィールドがchromeに持っているものですが、これはブラウザ間で互換性があり、すべてのブラウザでプレゼンテーションを完全に制御できるようにしたいです)。
ビューのコード:
<input data-ng-model="session.amountChosen" type="text" min="1" class="form-control input-small" data-number-input>
ディレクティブコード:
app.directive('numberInput', function() {
return {
require: 'ngModel',
scope: true,
link: function(scope, Elm, attrs, ctrl) {
var currValue = parseInt(scope.$eval(attrs.ngModel)),
minValue = attrs.min || 0,
maxValue = attrs.max || Infinity,
newValue;
//puts a wrap around the input and adds + and - buttons
Elm.wrap('<div class="number-input-wrap"></div>').parent().append('<div class="number-input-controls"><a href="#" class="btn btn-xs btn-pluimen">+</a><a href="#" class="btn btn-xs btn-pluimen">-</a></div>');
//finds the buttons ands binds a click event to them where the model increase/decrease should happen
Elm.parent().find('a').bind('click',function(e){
if(this.text=='+' && currValue<maxValue) {
newValue = currValue+1;
} else if (this.text=='-' && currValue>minValue) {
newValue = currValue-1;
}
scope.$apply(function(){
scope.ngModel = newValue;
});
e.preventDefault();
});
}
};
})
これは、scope。$ eval(attrs.ngModel)を介して現在のモデル値を取得できますが、新しい値を設定できません。
余波編集:これは現在機能するコードです(この問題の解決策を見たくない場合)
app.directive('numberInput', function() {
return {
require: 'ngModel',
scope: true,
link: function(scope, Elm, attrs, ctrl) {
var minValue = attrs.min || 0,
maxValue = attrs.max || Infinity;
Elm.wrap('<div class="number-input-wrap"></div>').parent().append('<div class="number-input-controls"><a href="#" class="btn btn-xs btn-pluimen">+</a><a href="#" class="btn btn-xs btn-pluimen">-</a></div>');
Elm.parent().find('a').bind('click',function(e){
var currValue = parseInt(scope.$eval(attrs.ngModel)),
newValue = currValue;
if(this.text=='+' && currValue<maxValue) {
newValue = currValue+1;
} else if (this.text=='-' && currValue>minValue) {
newValue = currValue-1;
}
scope.$eval(attrs.ngModel + "=" + newValue);
scope.$apply();
e.preventDefault();
});
}
};
})
ngModelController $ eval()の代わりにメソッドを使用して、ng-modelプロパティの値を取得および設定する必要があります。
$ evalは値を数値に変換するため、数値を持つ属性を評価する場合、parseInt()は必要ありません。 $ evalを使用して、変数minValueおよびmaxValueを設定する必要があります。
ディレクティブで子スコープを作成する必要はありません。
ngModelControllerメソッド(特に$ render())が自動的にビューを更新するため、$ apply()は必要ありません。ただし、@ Harijsが以下のコメントで注記しているように、アプリの他の部分も更新する必要がある場合は$ apply()が必要です。
app.directive('numberInput', function ($parse) {
return {
require: 'ngModel',
link: function (scope, Elm, attrs, ctrl) {
var minValue = scope.$eval(attrs.min) || 0,
maxValue = scope.$eval(attrs.max) || Infinity;
Elm.wrap('<div class="number-input-wrap"></div>').parent()
.append('<div class="number-input-controls"><a href="#" class="btn btn-xs btn-pluimen">+</a><a href="#" class="btn btn-xs btn-pluimen">-</a></div>');
Elm.parent().find('a').bind('click', function (e) {
var currValue = ctrl.$modelValue,
newValue;
if (this.text === '+' && currValue < maxValue) {
newValue = currValue + 1;
} else if (this.text === '-' && currValue > minValue) {
newValue = currValue - 1;
}
ctrl.$setViewValue(newValue);
ctrl.$render();
e.preventDefault();
scope.$apply(); // needed if other parts of the app need to be updated
});
}
};
});
scope.ngModel
変数を置き換えるのではなく、その変数の背後にある値を置き換えます。リンク関数の最初の行の値を読んだとき、あなたはすでにそれをしました:
currValue = parseInt(scope.$eval(attrs.ngModel))
// ^^^^^^^^^^^^^^^^^^^^
myProperty
のようなプレーンな値の場合は、スコープで使用できます。
scope[attr.ngModel] = newValue
ただし、container.myProperty
のようなexpression-valueがある場合、これは機能しません。その場合(これはより一般的なタイプであり、狙っているはずです)、スコープに設定されている値を次のように評価する必要があります。
scope.$eval(attrs.ngModel + "=" + newValue)
eval
ペンダントを使用したJavaScriptの場合と同様に、$eval
の部分は少し見苦しいことを認めざるを得ませんが、それでうまくいきます。文字列値を設定する場合は、この方法では機能しない可能性があることに注意してください。次に、それらの値をエスケープする必要があります。
それが役に立てば幸い;)
.directive('numberInput', function ($parse) {
return {
require: 'ngModel',
link: function (scope, Elm, attrs){
Elm.bind("click", function() {
var model = $parse(attrs.ngModel);
var modelSetter = model.assign;
scope.$apply(function() {
modelSetter(scope, model);
});
}
}
})