【问题标题】:Model not updating in Angular.js directive for bootstrap-multiselect模型未在 Angular.js 指令中更新 bootstrap-multiselect
【发布时间】:2014-04-20 21:53:08
【问题描述】:

我有以下指令:

app.directive('scMultiselect', [function() {
    return {
        link: function(scope, element, attrs) {
            element = $(element[0]);

            element.multiselect({
                enableFiltering: true,

                // Replicate the native functionality on the elements so
                // that Angular can handle the changes for us
                onChange: function(optionElement, checked) {
                    optionElement.prop('selected', false);

                    if (checked)
                        optionElement.prop('selected', true);

                    element.change();
                }
            });

            scope.$watch(function () {
                return element[0].length;
            }, function () {
                element.multiselect('rebuild');
            });

            scope.$watch(attrs.ngModel, function() {
                element.multiselect('refresh');
            });
        }
    };
}]);

以及我部分中的以下元素:

<select
    id="level_teachers"
    class="multiselect col-sm-10"
    multiple="multiple"
    ng-model="level.teachers"
    ng-options="teacher.id as teacher.name for teacher in teachers"
    sc-multiselect>
</select>

bootstrap-multiselect 控件初始化并正确显示,但是当我在其中选择条目时,我的模型 (level.teachers) 仍然为空。

【问题讨论】:

    标签: angularjs bootstrap-multiselect


    【解决方案1】:

    有同样的问题,这对我有用:

    首先你添加 ngModel 作为链接函数的第四个参数。它非常有用 - 更多关于它的信息:https://docs.angularjs.org/api/ng/type/ngModel.NgModelController

    然后您基本上必须在 onChange 方法中向/从您的 ngModel 中“手动”添加/删除选项。

    ngModel.$setViewValue() 更新值,ngModel.$render 和 scope.$apply() 使其可见并进一步传播新模型:)

    如果你只有一个选择,那么它会更容易 - 因为没有数组控制,所以代码更少 - 只需使用 $setViewValue()、$render() 和 $apply()。

    app.directive('scMultiselect', function() {
        return {
            require: 'ngModel',
            link: function(scope, element, attrs, ngModel) {
                element = $(element[0]);
    
                element.multiselect({
                    enableFiltering: true,
                    onChange: function(optionElement, checked) {
                        optionElement.prop('selected', false);
    
                        var modelValue = ngModel.$modelValue; // current model value - array of selected items
                        var optionText = optionElement[0].text; // text of current option
                        var optionIndex = modelValue.indexOf(optionText); 
                        if (checked) {
                            if ( optionIndex == -1) { // current option value is not in model - add it
                                modelValue.push(optionText)
                            }
                            optionElement.prop('selected', true);
                        } else if ( optionIndex > -1 ) { // if it is - delete it
                            modelValue.splice(optionIndex,1);
                        }
    
                        ngModel.$setViewValue(modelValue);
                        ngModel.$render();
                        scope.$apply();
                    }
                });
    
                scope.$watch(element[0].length, function () {
                    element.multiselect('rebuild');
                });
            }
        };
    });
    

    希望它也对你有用:)

    【讨论】:

    • 非常好!花几个小时解决这个问题!
    • 我也是,所以我很高兴它有帮助:)
    【解决方案2】:

    这可能是因为 Bootstrap 组件不是以允许 Angularjs 使用它们的方式构建的。在您实例化它们之后,它们实际上并没有办法更新自己,更重要的是,它们不参与 Angularjs 的更新过程。无论如何,好消息是有人主动在 Angularjs 中重写了这些引导组件,以便我们可以使用它们。

    http://angular-ui.github.io/bootstrap/

    如果您使用的是 Bootstrap 3.x,请获取最新版本。如果你卡在 2.3.x v0.8 是支持 2.3.x 的最后一个版本

    【讨论】:

    • 我使用的不是 Bootstrap 组件。我想这更像是一个 Angular.js 问题而不是 Bootstrap 问题,因为它与 Bootstrap 关系不大。
    猜你喜欢
    • 1970-01-01
    • 2013-12-28
    • 1970-01-01
    • 2014-12-09
    • 1970-01-01
    • 1970-01-01
    • 2014-07-02
    • 1970-01-01
    • 2017-07-22
    相关资源
    最近更新 更多