我正在使用ui-select插件,并且我将ng-model从我的控制器传递到名为richSelect的自定义指令,但ng-model似乎没有更新任何选择项目
<richselect ng-model="dataModel"></richselect>
自定义指令
app.directive('richselect', ['$compile', function ($compile) {
return {
restrict: 'AE',
scope: {
ngModel: '=' /* Model associated with the object */
},
link: function (scope, element, attrs, ngModel) {
scope.options = [
{
'Value' : 'value1',
'Desc' : 'Value One'
},
{
'Value' : 'value2',
'Desc' : 'Value Two'
}
]
scope.getRichSelectTemplate = function () {
return '<ui-select multiple ng-model="ngModel" theme="bootstrap" ng-disabled="disabled">' +
'{{ngModel}} <ui-select-match placeholder="Select">{{$select.selected.Desc}}</ui-select-match>' +
'<ui-select-choices repeat="option in options | filter: $select.search">' +
'<span ng-bind-html="option.Desc | highlight: $select.search"></span>' +
'</ui-select-choices>' +
'</ui-select>';
}
var linkFn = $compile(scope.getRichSelectTemplate())(scope);
element.append(linkFn);
}
}
}]);
答案 0 :(得分:1)
在这里,试试这个。我不确定您尝试获取的格式或输出,但这会将选定的选项传递给View。
您必须使用ngModel.$setViewValue
才能在视图中更改指令中ng-model的值。另外,要获得ui-select的值,您需要将ng-model指向options.selected
然后,只需要添加ng-click
指向使用ngModel.$setViewValue(scope.options.selected
更新视图的函数。
另外,我相信你需要在你的指令中`require:'ngModel',这样你才能访问ngModelController。
app.directive('richselect', ['$compile', function ($compile) {
return {
restrict: 'AE',
require: 'ngModel',
scope: {
blah: '=' /* Model associated with the object */
},
link: function (scope, element, attrs, ngModel) {
scope.changer = function() {
ngModel.$setViewValue(scope.options.selected)
console.log(scope.options.selected)
}
scope.options = [
{
'Value' : 'value1',
'Desc' : 'Value One'
},
{
'Value' : 'value2',
'Desc' : 'Value Two'
}
]
scope.getRichSelectTemplate = function () {
return '<ui-select multiple ng-model="options.selected" theme="bootstrap" ng-click="changer()" ng-disabled="disabled">' +
'{{options.selected}} <ui-select-match placeholder="Select">{{$select.selected.Desc}}</ui-select-match>' +
'<ui-select-choices repeat="option in options | filter: $select.search">' +
'<span ng-bind-html="option.Desc | highlight: $select.search"></span>' +
'</ui-select-choices>' +
'</ui-select>';
}
var linkFn = $compile(scope.getRichSelectTemplate())(scope);
element.append(linkFn);
}
}
}]);
修改强> 经过大量的挖掘和修补,根据下面的评论 - 获得双向约束工作已经证明有点难以捉摸。我发现使用标准的ui-select指令非常容易,如此处所示(来自ui-select的修改示例代码),因为我们可以轻松访问指令的范围: Standard Directive Demo
我也遇到了与OP中的一个类似的包装,但是在使用它之后,那个似乎有同样的问题 - 很容易把东西拿出去,但是如果你需要将数据推送到指令中不想去。 有趣的是,在上面的解决方案中,我可以看到`scope.options.selected'对象实际上包含数据,它永远不会落在ui-select指令的范围内,因此永远不会允许我们推送数据。
在我正在处理的项目中遇到与其他包装器指令类似的问题之后,我想出了如何通过不同的范围推送数据。
我的解决方案是修改ui-select脚本本身,添加一个内部$ watch函数,检查其$parent
范围内的变量。由于ui-select指令使用scope: true
,因此它创建了一个子范围(如果我没有记错,那么父级将是此OP中的指令)。
在uiSelect指令的link函数的底部,我添加了以下监视功能:
scope.$watch(function() {
return scope.$parent.myVar;
}, function(newVal) {
$select.selected = newVal;
})
在我们的直接链接功能中,我添加了这个$ watch功能:
scope.$watch(function() {
return ngModel.$viewValue;
}, function(newVal) {
scope.myVar = newVal;
})
所以这里发生的是,如果$ viewValue发生了变化(即,我们将一些来自http服务的数据等分配给dataModel
绑定,$ watch函数将捕获它并将其分配给范围。 myVar.ui-select脚本中的$ watch函数监视范围。$ parent.myVar用于更改(我们告诉它在其父级的范围内观察变量)。如果它看到任何更改,则将它们推送到 $select.selected
- 这就是ui-select通过单击下拉列表中的项目来保留已选择的任何值的地方。我们只需覆盖它并插入我们想要的任何值。
<强> Plunker - Two-way binding 强>
答案 1 :(得分:0)
首先,dataModel
是一个字符串。由于您定义了multiple
,因此模型将是一个数组。
更重要的是uiSelect
指令创建了一个新范围。这意味着ng-model="ngModel"
不再指向dataModel
。你有效地破坏了绑定。
在你的控制器中使dataModel
成为一个对象:
$scope.dataModel = {};
在您的指令中,让选定的值绑定到属性:
return '<ui-select multiple ng-model="ngModel.selection"
现在所选的值将绑定到dataModel.selection
。
如果您不使用ngModelController
,则不应在您的指令中使用ng-model
。