Bootstrap-multiselect: KnockoutJS ๊ฐ์ฒด ๊ฐ’ ๋ฐ”์ธ๋”ฉ(๋‹จ์ˆœ ๊ฐ’ ์•„๋‹˜) ... ํ•ดํ‚น ์ˆ˜์ • ํฌํ•จ

์— ๋งŒ๋“  2015๋…„ 05์›” 02์ผ  ยท  3์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: davidstutz/bootstrap-multiselect

์ „์ฒด ๊ฐœ์ฒด๊ฐ€ ๋ฌธ์ž์—ด์ด ์•„๋‹Œ ๊ฐ’์œผ๋กœ ๋ฐ”์ธ๋”ฉ๋˜๋Š” ๋…น์•„์›ƒ ์„ ํƒ ๋ฐ”์ธ๋”ฉ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

bootstrap-multiselect๋Š” ๋“œ๋กญ๋‹ค์šด ๋ชฉ๋ก ํ•ญ๋ชฉ์„ ํ•ด๋‹น ์„ ํƒ ์˜ต์…˜๊ณผ ๋‹ค์‹œ ์—ฐ๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด "๊ฐ’"์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์„ ์ข‹์•„ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด ๋…น์•„์›ƒ ๋ฐ”์ธ๋”ฉ์— "optionsValue" ์†์„ฑ์„ ์„ค์ •ํ•˜์—ฌ ์˜ต์…˜์— "๊ฐ’" ์†์„ฑ์ด ์žˆ๋„๋ก ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ "optionsValue" ์†์„ฑ์„ ์„ค์ •ํ•˜๋ฉด ์ „์ฒด ๊ฐ์ฒด๊ฐ€ ์•„๋‹Œ ๋‚ด selectedOptions observableArray์—์„œ ํ•ด๋‹น ๊ฐ’๋งŒ ์„ค์ •ํ•˜๋Š” ์˜ˆ์ƒ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

์˜ต์…˜์„ ์ „์ฒด ๊ฐœ์ฒด์— ๋ฐ”์ธ๋”ฉํ•  ์ˆ˜ ์žˆ๋Š” ๋…น์•„์›ƒ ๋‚ด ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋Š” ์œ ์ผํ•œ ์‚ฌ๋žŒ์ด ๋‚˜์ผ ๊ฐ€๋Šฅ์„ฑ์ด ๋งค์šฐ ๋†’์ง€๋งŒ ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ๋ฅผ ๋Œ€๋น„ํ•˜์—ฌ... ์—ฌ๊ธฐ ํ•ดํ‚น ์ˆ˜์ • ์‚ฌํ•ญ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

"optionsKey" ๋ฐ "observableKey"๋ผ๋Š” ๋‘ ๊ฐœ์˜ ์ƒˆ๋กœ์šด ๋ถ€ํŠธ์ŠคํŠธ๋žฉ ๋‹ค์ค‘ ์„ ํƒ ์˜ต์…˜์„ ์ƒ์„ฑํ•˜์—ฌ ๊ด€๋ จ๋  ์ˆ˜ ์žˆ๋Š” ๊ฐ’์„ ์–ด๋””๋กœ ๊ฐ€์•ผ ํ•˜๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<select id="mySelect" data-bind="options: myOptions, selectedOptions: mySelectedOptions, optionsText: 'myDisplayText', optionsAfterRender: SetOptionKey, multiselect: { optionsKey: 'data-key', observableKey: 'Key' }" multiple="multiple"></select>

๋‚ด ๋…น์•„์›ƒ ๋ณด๊ธฐ ๋ชจ๋ธ์—์„œ ๊ฐ ์˜ต์…˜์— ๋Œ€ํ•ด "optionsKey"๊ฐ€ ์ฐธ์กฐํ•˜๋Š” ์†์„ฑ์„ ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

myVM.SetOptionKey = function ( option, item ) {
    ko.applyBindingsToNode( option, { attr: { "data-key": item.Key } }, item );
};

์ด์ œ bootstrap-multiselect.js ํŒŒ์ผ์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—์„œ ๊ฐ€์žฅ ๋จผ์ € ํ•ด์•ผ ํ•  ์ผ์€ ๋…น์•„์›ƒ ์ดˆ๊ธฐํ™” ์ฒ˜๋ฆฌ๊ธฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ์ƒ๋‹จ์— ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
    ...
    if (allBindings.has('selectedOptions')) {
        var selectedOptions = allBindings.get('selectedOptions');
        if (ko.isObservable(selectedOptions)) {
            ko.computed({
                read: function () {
                    selectedOptions();

                    // Added to handle knockout binding to an object...not just a value
                    // multiselect needs the selected property on the options, else it wont show them on refresh
                    if ((config.optionsKey !== undefined) &&
                        (config.optionsKey !== null) &&
                        (config.optionsKey.length > 0) &&
                        (config.observableKey !== undefined) &&
                        (config.observableKey !== null) &&
                        (config.observableKey.length > 0)) {
                        var _optionsKey = config.optionsKey;
                        var _observableKey = config.observableKey;
                        ko.utils.arrayForEach(selectedOptions(), function (selectedOption) {
                            $("option[" + _optionsKey + "='" + selectedOption[_observableKey]() + "']", $element).prop('selected', true);
                        })
                    }

                    setTimeout(function () {
                        $element.multiselect('refresh');
                    }, 1);
                },
                disposeWhenNodeIsRemoved: element
            }).extend({ rateLimit: 100, notifyWhenChangesStop: true });
        }
    }
    ...

๋‹ค์Œ์œผ๋กœ bootstrap-multiselect.js์˜ createOptionValue ํ•จ์ˆ˜๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ ๋จผ์ € ์ด ํ‚ค๋ฅผ ๋ชฉ๋ก ํ•ญ๋ชฉ์— ์„ค์ •ํ•˜๋Š” ๊ฐ’์œผ๋กœ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

createOptionValue: function (element) {
    ...

    var value = $element.val();
    // Added to handle knockout binding to an object...not just a value
    if ((this.options.optionsKey !== undefined) && (this.options.optionsKey !== null) && (this.options.optionsKey.length > 0)) {
        var key = $element.attr(this.options.optionsKey);
        if ((key !== undefined) && (key !== null) && (key.length > 0)) {
            value = key;
        }
    }

    ...
}

๋งˆ์ง€๋ง‰์œผ๋กœ ๊ฐ’ ๋Œ€์‹  ์ด ์†์„ฑ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์˜ต์…˜ ์š”์†Œ๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด bootstrap-multiselect.js์—์„œ getOptionByValue ํ•จ์ˆ˜๋ฅผ ์ˆ˜์ •ํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

getOptionByValue: function (value) {
    var valueToCompare = value.toString();

    // Added to handle knockout binding to an object...not just a value
    if ((this.options.optionsKey !== undefined) && (this.options.optionsKey !== null) && (this.options.optionsKey.length > 0)) {
        var opt = $("option[" + this.options.optionsKey + "='" + valueToCompare + "']", this.$select).first();
        if( (opt !== undefined) && (opt !== null) ) {
            return $(opt);
        }
    }

    var options = $('option', this.$select);

    for (var i = 0; i < options.length; i = i + 1) {
        var option = options[i];
        if (option.value === valueToCompare) {
            return $(option);
        }
    }
},
question

๋ชจ๋“  3 ๋Œ“๊ธ€

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. FAQ์— ํฌํ•จํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค! ๋‚˜๋Š” ์ด๊ฒƒ์ด ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž์—๊ฒŒ๋„ ๋„์›€์ด ๋  ๊ฒƒ์ด๋ผ๊ณ  ํ™•์‹ ํ•ฉ๋‹ˆ๋‹ค.

์ด ํŒ์„ ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๊ฐœ์ฒด ์„ ํƒ์— ๋Œ€ํ•œ ๋ฐ”์ธ๋”ฉ๋„ ์ˆ˜ํ–‰ํ•˜๋ ค๊ณ  ํ–ˆ์œผ๋ฉฐ ์ด ๊ธ€์ด ๋งค์šฐ ๋„์›€์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. @APM3 ์˜ ์ฝ”๋“œ ์™ธ์— ๋‚ด๊ฐ€ ํ•ด์•ผ ํ•  ์œ ์ผํ•œ ์ผ์€ SetOptionKey ํ•จ์ˆ˜์—์„œ ๋‚ด ์˜ต์…˜์˜ "๊ฐ’" ์†์„ฑ๋„ ์ฑ„์šฐ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

self.SetOptionKey = function (option, item) { ko.applyBindingsToNode(option, { attr: { "data-key": item.Value } }, item); ko.applyBindingsToNode(option, { attr: { "value": item.Value } }, item); }

์ด ๊ธ€์„ ์จ์ฃผ์…”์„œ ๋‹ค์‹œ ํ•œ ๋ฒˆ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

์ง€์›ํ•˜๋Š” ๊ฐœ์ฒด์˜ ๋…น์•„์›ƒ ๋ฐ”์ธ๋”ฉ์€ ์š”์ง€ ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”. bootstrap-multiselect.js ํŒŒ์ผ์—์„œ ์‹ค์ œ ๋ฐ”์ธ๋”ฉ์„ ๊ต์ฒดํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ด ์ฝ”๋“œ์—์„œ๋Š” ์˜ต์…˜์„ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด VM์— ๋„ฃ์„ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

//Just like this one
myVM.SetOptionKey = function ( option, item ) {
    ko.applyBindingsToNode( option, { attr: { "data-key": item.Key } }, item );
};

์•”์‹œ์ ์œผ๋กœ optionsAfterRender ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด ๋ฐ”์ธ๋”ฉ์— ์ „์ฒ˜๋ฆฌ ๋ฅผ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰