gpt4 book ai didi

angularjs - select2、ng-model 和 Angular

转载 作者:行者123 更新时间:2023-12-03 06:55:09 33 4
gpt4 key购买 nike

使用jquery-select2 (不是 ui-select)和 Angular ,我正在尝试将值设置为 ng-model。

我尝试过使用 $watchng-change,但在使用 select2 选择项目后似乎都没有触发。

不幸的是,我使用的是购买的模板,无法使用 angular-ui。

HTML:

<input type="hidden" class="form-control select2remote input-medium"
ng-model="contact.person.id"
value="{{ contact.person.id }}"
data-display-value="{{ contact.person.name }}"
data-remote-search-url="api_post_person_search"
data-remote-load-url="api_get_person"
ng-change="updatePerson(contact, contact.person)">

客户端 Controller :

$scope.updatePerson = function (contact, person) {
console.log('ng change');
console.log(contact);
console.log(person);
} // not firing

$scope.$watch("client", function () {
console.log($scope.client);
}, true); // not firing either

JQuery 集成:

var handleSelect2RemoteSelection = function () {
if ($().select2) {
var $elements = $('input[type=hidden].select2remote');
$elements.each(function(){
var $this = $(this);
if ($this.data('remote-search-url') && $this.data('remote-load-url')) {
$this.select2({
placeholder: "Select",
allowClear: true,
minimumInputLength: 1,
ajax: { // instead of writing the function to execute the request we use Select2's convenient helper
url: Routing.generate($this.data('remote-search-url'), {'_format': 'json'}),
type: 'post',
dataType: 'json',
delay: 250,
data: function (term, page) {
return {
query: term, // search term
};
},
results: function (data, page) { // parse the results into the format expected by Select2.
return {
results: $.map(data, function (datum) {
var result = {
'id': datum.id,
'text': datum.name
};
for (var prop in datum) {
if (datum.hasOwnProperty(prop)) {
result['data-' + prop] = datum[prop];
}
}
return result;
})
}
}
},
initSelection: function (element, callback) {
// the input tag has a value attribute preloaded that points to a preselected movie's id
// this function resolves that id attribute to an object that select2 can render
// using its formatResult renderer - that way the movie name is shown preselected
var id = $(element).val(),
displayValue = $(element).data('display-value');
if (id && id !== "") {
if (displayValue && displayValue !== "") {
callback({'id': $(element).val(), 'text': $(element).data('display-value')});
} else {
$.ajax(Routing.generate($this.data('remote-load-url'), {'id': id, '_format': 'json'}), {
dataType: "json"
}).done(function (data) {
callback({'id': data.id, 'text': data.name});
});
}
}
},
});
}
});
}
};

如有任何建议,我们将不胜感激! :)

更新

我已经成功地将 a plunk 放在一起这似乎同样重现了问题 - 现在看起来好像 ng-watch 和 $watch 事件仅在第一次更改值时才被触发。然而,在我的代码中(以及当添加进一步的复杂性时,例如动态添加和从集合中删除),它甚至似乎不会触发一次。

再次,如果您能指出正确的方向(或实际上任何方向),我们将不胜感激!

最佳答案

您的示例存在许多问题。我不确定我是否能够提供“答案”,但希望以下建议和解释能够帮助您。

首先,您“混合”了 jQuery 和 Angular。一般来说,这确实行不通。例如:

在 script.js 中,您运行

$(document).ready(function() {
var $elements = $('input[type=hidden].select2remote');
$elements.each(function() {
//...
});
});

当 DOM 最初准备好时,此代码将运行一次。它将选择当前位于 DOM 中的 select2remote 类的隐藏输入元素,并在其上初始化 select2 插件。

问题是,运行此函数后添加的任何新 input[type=hidden].select2remote 元素根本不会被初始化。例如,如果您异步加载数据并填充 ng-repeat,就会发生这种情况。

修复方法是将 select2 初始化代码移动到指令中,并将该指令放置在每个输入元素上。删节后,该指令可能如下所示:

.directive('select2', function() {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attr, ngModel) {

//$this becomes element

element.select2({
//options removed for clarity
});

element.on('change', function() {
console.log('on change event');
var val = $(this).value;
scope.$apply(function(){
//will cause the ng-model to be updated.
ngModel.setViewValue(val);
});
});
ngModel.$render = function() {
//if this is called, the model was changed outside of select, and we need to set the value
//not sure what the select2 api is, but something like:
element.value = ngModel.$viewValue;
}

}
}
});

抱歉,我对 select2 不够熟悉,不知道用于获取和设置控件当前值的 API。如果您在评论中向我提供这一点,我可以修改该示例。

您的标记将更改为:

<input select2 type="hidden" class="form-control select2remote input-medium"
ng-model="contact.person.id"
value="{{ contact.person.id }}"
data-display-value="{{ contact.person.name }}"
data-remote-search-url="api_post_person_search"
data-remote-load-url="api_get_person"
ng-change="updatePerson(contact, contact.person)">

实现此指令后,您可以删除整个 script.js。

在您的 Controller 中,您有以下内容:

$('.select2remote').on('change', function () {
console.log('change');
var value = $(this).value;
$scope.$apply(function () {
$scope.contact.person.id = value;
});
});

这里有两个问题:

首先,您在 Controller 中使用 jQuery,您确实不应该这样做。
其次,这行代码将在整个应用程序中的 select2remote 类的每个元素上触发一个更改事件,该类在 Controller 启动时位于 DOM 中。/p>

由 Angular 添加的元素(即通过 ng-repeat)很可能不会在其上注册更改监听器,因为它们将在 Controller 实例化后(在下一个消化周期)。

此外, Controller 范围之外具有更改事件的元素将修改 Controller 的 $scope 的状态。解决方案再次是将此功能移至指令中并依赖 ng-model 功能。

请记住,无论何时离开 Angular 的上下文(即,如果您使用 jQuery 的 $.ajax 功能),都必须使用scope.$apply() 重新进入 Angular 的执行上下文。

希望这些建议对您有所帮助。

关于angularjs - select2、ng-model 和 Angular,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29880950/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com