首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当选择的下拉值发生变化时,可观察到的剔除不是在更新。

当选择的下拉值发生变化时,可观察到的剔除不是在更新。
EN

Stack Overflow用户
提问于 2016-06-23 20:13:29
回答 1查看 832关注 0票数 1

我们一直在使用Chosen库与RequireJsKnockOut。一切都很好,直到我们从RequireJS切换到commonjs,现在使用webpack进行捆绑。问题是,当我们更改knockout observable下拉列表中的值时,chosen不会被更新。

下面是使用RequireJs的javascript代码。

代码语言:javascript
复制
define(['knockout', 'text!./employee-setup.html', 'utils', 'panel-section', 'toastr', 'jquery', 'knockout-postbox', 'knockout-projections', 'chosen', 'jsteps'], function (ko, template, utils, PanelSection, toastr, $, _, _, _, jsteps) {
function EmployeeSetup(params) {
    var self = this;
    this.agentTypes = ko.observableArray();
    this.agentType = ko.observable();


    this.loadAgentTypes = function () {
        $.ajax({
            url: '/Employee/GetAgentTypes',
            method: 'POST',
            dataType: 'json',
            success: function (result) {
                if (utils.handleAjaxResult(result) && result.Data) {
                    self.agentTypes([]);

                    var agentType = [{ ID: "", Name: "" }];

                    $.each(result.Data, function (i, item) {
                        agentType.push({ID: item.ID, Name: item.Name});
                    });
                    self.agentTypes(agentType);
                    $('#agentType').chosen({ allow_single_deselect: true, width: '310px' });
                    $('#agentType').trigger("chosen:updated");
                } else {
                }

            },
            error: function () {
                toastr.error('Could not load agent types');
            }
        });
    };
    self.loadAgentTypes();
    };
 return { template: template, viewModel: EmployeeSetup };
});

该组件的html:

代码语言:javascript
复制
<div class="input-container" data-bind="">
     <select data-bind="value: agentType, options: agentTypes, optionsText: 'Name'" data-placeholder="Select Agent Type..." id="agentType" class="chosen-select sp-uin-dropdown" tabindex="2"> </select>
</div>

下面是使用commonjs的代码

代码语言:javascript
复制
var ko = require('knockout'),
    utils = require('utils'),
    PanelSection = require('panel-section'),
    toastr = require('toastr'),
    $ = require('jquery');
require('knockout-postbox');

function ViewModel(params) {
   var self = this;
   this.agentTypes = ko.observableArray();
   this.agentType = ko.observable();

   this.loadAgentTypes = function () {
   $.ajax({
       url: '/Employee/GetAgentTypes',
       method: 'POST',
       dataType: 'json',
       success: function (result) {
       if (utils.handleAjaxResult(result) && result.Data) {
              self.agentTypes([]);

              var agentType = [{ ID: "", Name: "" }];

              $.each(result.Data, function (i, item) {
                  agentType.push({ID: item.ID, Name: item.Name});
              });
              self.agentTypes(agentType);
              $('#agentType').chosen({ allow_single_deselect: true, width: '310px' });
              $('#agentType').trigger("chosen:updated");
            } else {
           }
        },
        error: function () {
           toastr.error('Could not load agent types');
        }
    });
  };
  self.loadAgentTypes();
}
module.exports = { viewModel: ViewModel, template: require('./template.html')      };

它使用与上面相同的html文件。

webpack.config.js中,我们定义了jquerychosen的路径。

它正确地加载chosen dropdown。然而,当我的subscribe被观察到时,当下拉列表发生变化时,它不会更新值。在初始加载时,我只从控制台看到一次值。

代码语言:javascript
复制
self.agentType.subscribe(function (value) {
    console.log('value', value);
}, this)

这里很少有这样建议使用bindingHandlers的帖子。我已经在我的应用程序中尝试过来自JSFiddle的这个工作代码,但是我只从初始加载中得到了这个值。

对于如何解决这个问题,或者是什么原因,有什么建议吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-07-01 20:29:36

这个问题是由webpack引起的。为了解决这个问题,我的同事写了一个定制的bindingHandler

HTML代码:

代码语言:javascript
复制
<div class="input-container">
 <select data-bind="
                value: agentType,
                options: agentTypes, 
                optionsText: 'Name',
                dropdown: {
                    width: '310px',
                    allow_single_deselect: true
                } "
                data-placeholder="Select Agent Type..." id="agentType">
</select>

自定义bindingHandler

代码语言:javascript
复制
// a dropdown handler, which currently utilizes the Chosen library

ko.bindingHandlers.dropdown = {

    init: function(element, valueAccessor, allBindings, viewModel, bindingContext){

        // get chosen element

        var $element = $(element);

        // get options (if any) to pass to chosen when creating

        var options = ko.unwrap(valueAccessor());



        // NOTE: when using Chosen w/ webpack, the knockout bindings no longer

        // fired. This event handler is to remedy that. It watches the change

        // event for the underlying <select> (which chosen updates), and

        // updates the corresponding observables mapped to value and selectedOptions.

        // Only one should be bound, value for single select, selectedOptions for multi-select

        // binding direction: Knockout <- Chosen

        $element.on('change', function(e, item) {

            var valueProp = allBindings.has('value') && allBindings.get('value');

            var selectedOptionsProp = allBindings.has('selectedOptions') && allBindings.get('selectedOptions');

            if (item) {

                if (allBindings.has('options')) {

                    var allOptions = ko.unwrap(allBindings.get('options'));

                    if (valueProp) {

                        // single select

                        if (ko.isObservable(valueProp)) {

                            if (!item.isMultiple) {

                                if (item.selecting) {

                                    valueProp(allOptions[item.index]);

                                } else {

                                    valueProp(null);

                                }

                            }

                        }

                    }

                    if (selectedOptionsProp) {

                        // multi select

                        if (ko.isObservable(selectedOptionsProp)) {

                            if (item.isMultiple) {

                                // handle multi select

                                if (item.selecting) {

                                    // select

                                    selectedOptionsProp.push(allOptions[item.index]);

                                } else {

                                    // deselect

                                    selectedOptionsProp.remove(allOptions[item.index]);

                                }

                            }

                        }

                    }

                }

            } else {

                // this is triggered w/o args when the control is reset. This happens when deselecting during single-select

                if (valueProp) {

                    // single select

                    if (item === undefined && ko.isObservable(valueProp)) {

                        valueProp(null);

                    }

                }

            }

        });
        // handle updating the chosen component's UI when the underlying

        // options, selectedOptions or value changes

        // binding direction: Knockout -> Chosen

        ['options', 'selectedOptions', 'value'].forEach(function(propName){

            if (allBindings.has(propName)){

               var prop = allBindings.get(propName);

                if (ko.isObservable(prop)){

                    //console.log('subscribing to:', propName, ' for:', $element);

                    prop.subscribe(function(value){

                        if (value != null) {

                            //console.log('calling chosen:updated');

                            var options = ko.unwrap(allBindings.get('options'));

                            // console.log('got options:', options);

                            if (options) {

                                if (options.indexOf(value) > -1) {

                                    // item is in options

                                    //        console.log('value is in options:', value);

                                } else {

                                    // item is not in options, try to match ID

                                    options.some(function (item) {

                                        if (item.ID == value) {

                                            // update the obs. to the entire item, not the ID

                                            prop(item);

                                        }

                                    });

                                }

                            }

                        }

                        $element.trigger('chosen:updated');

                    });

                }

            }

        });       

        // add chosen css class (not sure this is needed)

        $element.addClass('chosen-select');



        // create chosen element, passing in options if any were specified

       if (typeof options === 'object') {

            $element.chosen(options);

        } else {

            $element.chosen();

        }

        $element.trigger('chosen:updated');

    }

};
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38000962

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档