我正在学习Angular。作为练习,我正在转换使用jQuery的现有应用程序来使用Angular。
在我的页面上,我有两个输入。一个是组合框;另一个是文本输入。
当用户更改组合框中的选择时,文本输入将填充用户选择的文本,除非用户在组合框中选择名为“自定义”的条目。当用户选择“自定义”时,文本输入被清除,焦点自动移动到文本输入,供用户键入自定义值。
每当用户手动将焦点移动到文本输入并键入某些内容时,组合框的值会自动更改为“自定义”。
在Angular中进行此操作的适当方法是什么?
我想如果我有两个相同的文本输入,我可以将它们绑定到同一个模型,但这是不同的。我猜我必须捕获事件并手动更新模型,但我想听听更多有经验的人。
答案 0 :(得分:5)
您可以在控制器的$watch
内包含一些逻辑,也可以更喜欢ng-click
和ng-change
等指令。
我认为Nikos Paraskevopoulos的答案很好,但它并没有真正解答你关于聚焦/清除输入的问题。
这是我实现这一目标的一种方式。首先是HTML模板。
<input type="text"
ng-model="vm.selected.value"
ng-change="vm.inputChanged()"
focus-when-empty>
<select ng-model="vm.selected.option"
ng-change="vm.selectionChanged()"
ng-options="option for option in vm.options">
</select>
这很清楚。文本input
和selection
有单独的模型,可供选择的一些选项和两者的ng-change
处理程序。控制器可能类似于
app.controller('MainController', function() {
var vm = this;
// your options to select from
vm.options = ['custom','one','two','three'];
// current text input value and dropdown selection
vm.selected = {
value: null,
option: null
};
// handle text input
vm.inputChanged = function() {
var index = vm.options.indexOf(vm.selected.value);
vm.selected.option = index > 0 ? vm.options[index] : vm.options[0];
};
// handle dropdown
vm.selectionChanged = function() {
var index = vm.options.indexOf(vm.selected.option);
vm.selected.value = index > 0 ? vm.selected.option : null;
};
});
当选择“自定义”时,专注于文本输入,有点棘手,所以它通过简单的focus-when-empty
指令处理。
app.directive('focusWhenEmpty', function() {
return {
restrict: 'A',
scope: {
ngModel: '='
},
link: function(scope, element) {
// if there is no model, focus on element
scope.$watch('ngModel', function(value) {
if (!value) {
element[0].focus();
}
});
}
};
});
另外一个额外的好处是,如果您在选项中键入任何值,则会相应地更新选择(因此它不再是“自定义”)。
这是相关的plunker,希望它有所帮助! http://plnkr.co/edit/uJeV5L
答案 1 :(得分:0)
很好的练习:)
传统的解决方案是使用手表并在输入上使用更改事件:
app.controller('Ctrl', function($scope) {
var self = this, changeIsInternal = false;
this.selection = null;
this.options = [
'custom',
'alpha',
'beta'
];
this.custom = null;
this.customChanged = function() {
if( this.selection !== 'custom' ) {
this.selection = 'custom';
changeIsInternal = true;
}
};
$scope.$watch(
function() {
return self.selection;
},
function(newval, oldval) {
if( newval !== oldval ) { // needed to skip initialization
if( changeIsInternal ) {
changeIsInternal = false;
}
else {
if( newval !== 'custom' ) {
self.custom = newval;
}
else {
self.custom = '';
}
}
}
}
);
});
及其相关的HTML:
<div ng-controller="Ctrl as ctrl">
<select ng-model="ctrl.selection" ng-options="o for o in ctrl.options"></select>
<br/>
<input ng-model="ctrl.custom" ng-change="ctrl.customChanged()" focus-when="ctrl.selection === 'custom'" />
<br/>
<pre><code>{{ ctrl | json }}</code></pre>
</div>
另一个解决方案是使用自定义对象属性;这使用 NO WATCHES ,我相信 Angular 2友好:
app.controller('Ctrl2', (function() {
function Ctrl2() {
this._selection = null;
this.options = [
'custom',
'alpha',
'beta'
];
this._custom = null;
}
Object.defineProperty(Ctrl2.prototype, 'selection', {
get: function() { return this._selection; },
set: function(value) {
if( value !== 'custom' ) {
this._custom = value;
}
else {
this._custom = '';
}
this._selection = value;
}
});
Object.defineProperty(Ctrl2.prototype, 'custom', {
get: function() { return this._custom; },
set: function(value) {
this._selection = 'custom';
this._custom = value;
}
});
return Ctrl2;
})());
HTML是相同的,省略了ng-change
部分。
(编辑:设定焦点...... ) 在这两种情况下,我建议使用以下指令来设置焦点:
app.directive('focusWhen', function($parse) {
return {
restrict: 'A',
scope: false,
link: function(scope, elem, attrs) {
scope.$watch(
$parse(attrs.focusWhen),
function(newval, oldval) {
if( newval && newval !== oldval ) {
elem[0].focus();
}
}
);
}
};
});
如果if( newval !== oldval )
的初始值为selection
,则"custom"
部分是为了防止焦点窃取。
这是一个更新的小提琴:http://jsfiddle.net/6dn55t5w/1/
(编辑评论...... )
Mikko Viitala的答案有趣地显示了用于监听选择框更改的ng-change
版本。这可能更适合这个问题(而不是使用手表),因为OP指出:&#34;当用户更改组合框中的选择时#34;。当模型也可以以编程方式更改时使用手表,因为在这种情况下不会触发更改事件。如果确保只有UI可以更改值,请使用ng-change
。
我仍然觉得Object.defineProperty
版本很有趣,因为它可以在没有手表的情况下处理UI和程序化更改。