【问题标题】:Knockout observable is not updating when Chosen dropdown value changesKnockout observable is not updating when Chosen dropdown value changes
【发布时间】:2016-06-23 20:13:29
【问题描述】:

我们一直在使用Chosen 库和RequireJsKnockOut。一切正常,直到我们从RequireJS 切换到commonjs,现在使用webpack 进行捆绑。问题是当我们更改 chosen 下拉列表中的值时,knockout observable 没有更新。

这是使用 RequireJs 工作的 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:

<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的代码

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 观察到时,它不会在下拉列表更改时更新值。我只在初始加载时从控制台看到过一次值。

self.agentType.subscribe(function (value) {
    console.log('value', value);
}, this)

这里很少有帖子建议使用bindingHandlers。我在我的应用程序中尝试了来自JSFiddle 的工作代码,但我只从初始加载中获取值。

关于如何解决此问题或导致此问题的任何建议?

【问题讨论】:

    标签: knockout.js webpack jquery-chosen commonjs


    【解决方案1】:

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

    HTML代码:

    <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:

    // 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');
    
        }
    
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-10
      • 2015-01-03
      • 2014-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-02
      • 1970-01-01
      相关资源
      最近更新 更多