[javascript] Knockout JS의 라디오 버튼에 참 / 거짓 바인딩

내 뷰 모델에는 true 또는 false 값이있는 IsMale 값이 있습니다.

내 UI에서 다음 라디오 버튼에 바인딩하고 싶습니다.

<label>Male
   <input type="radio" name="IsMale" value="true" data-bind="checked:IsMale"/>
</label>
<label>Female
   <input type="radio" name="IsMale" value="false" data-bind="checked:IsMale"/>
</label>

내가 생각하는 문제는 checked“true”/ “false”문자열을 기대한다는 것입니다 . 제 질문은이 UI와 모델을 사용하여이 양방향 바인딩을 어떻게 얻을 수 있습니까?



답변

한 가지 옵션은 쓰기 가능한 계산 된 Observable 을 사용하는 것 입니다.

이 경우, 좋은 옵션은 쓰기 가능 계산 된 관찰 가능 항목을 관찰 가능 항목의 “하위 관찰 가능 항목”으로 만드는 것 IsMale입니다. 보기 모델은 다음과 같습니다.

var ViewModel = function() {
   this.IsMale = ko.observable(true);

   this.IsMale.ForEditing = ko.computed({
        read: function() {
            return this.IsMale().toString();
        },
        write: function(newValue) {
             this.IsMale(newValue === "true");
        },
        owner: this
    });
};

다음과 같이 UI에서 바인딩합니다.

<label>Male
   <input type="radio" name="IsMale" value="true" data-bind="checked:IsMale.ForEditing"/>
</label>
<label>Female
   <input type="radio" name="IsMale" value="false" data-bind="checked:IsMale.ForEditing"/>
</label>

샘플 : http://jsfiddle.net/rniemeyer/Pjdse/


답변

나는 이것이 오래된 스레드라는 것을 알고 있지만 동일한 문제가 있었고이 질문이 공식적으로 답변 된 후 녹아웃에 추가 된 훨씬 더 나은 솔루션을 발견했기 때문에 동일한 문제를 가진 사람들에게 남겨 두겠습니다.

현재 Extender, 사용자 정의 바인딩 핸들러 또는 계산이 필요하지 않습니다. “checkedValue”옵션을 제공하면 html ‘value’속성 대신이 옵션을 사용하며 모든 javascript 값을 전달할 수 있습니다.

<input type="radio" name="a" data-bind="checked:IsChecked, checkedValue: true"/>
<input type="radio" name="a" data-bind="checked:IsChecked, checkedValue: false"/>

또는:

<input type="radio" name="b" data-bind="checked:Quantity, checkedValue: 1"/>
<input type="radio" name="b" data-bind="checked:Quantity, checkedValue: 2"/>
<input type="radio" name="b" data-bind="checked:Quantity, checkedValue: 3"/>


답변

이것은 나를 위해 작동합니다.

http://jsfiddle.net/zrBuL/291/

<label>Male
   <input type="radio" name="IsMale" value="1" data-bind="checked:IsMale"/>
</label>
<label>Female
   <input type="radio" name="IsMale" value="0" data-bind="checked:IsMale"/>
</label>


답변

ko.bindingHandlers['radiobuttonyesno'] = {
    'init': function (element, valueAccessor, allBindingsAccessor) {
        var stateHandler = function (property, allBindingsAccessor, key, value, checkIfDifferent) {
            if (!property || !ko.isObservable(property)) {
                var propWriters = allBindingsAccessor()['_ko_property_writers'];
                if (propWriters && propWriters[key])
                    propWriters[key](value);
            } else if (ko.isWriteableObservable(property) && (!checkIfDifferent || property.peek() !== value)) {
                property(value);
            }
        };

        var updateHandler = function () {
            var valueToWrite;

            if ((element.type == "radio") && (element.checked)) {
                valueToWrite = element.value;
            } else {
                return; // "radiobuttonyesno" binding only responds to selected radio buttons
            }

            valueToWrite = (valueToWrite === "True") ? true : false;

            var modelValue = valueAccessor(), unwrappedValue = ko.utils.unwrapObservable(modelValue); //can be true of false

            stateHandler(modelValue, allBindingsAccessor, 'checked', valueToWrite, true);
        };
        ko.utils.registerEventHandler(element, "click", updateHandler);

        // IE 6 won't allow radio buttons to be selected unless they have a name
        if ((element.type == "radio") && !element.name)
            ko.bindingHandlers['uniqueName']['init'](element, function () { return true });
    },
    'update': function (element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());

        value = value ? "True" : "False";

        if (element.type == "radio") {
            element.checked = (element.value == value);
        }
    }
};

어리석은 코 계산 관찰 가능 항목을 만드는 대신이 바인더를 사용하십시오.

예:

<label>Male
        <input type="radio" name="IsMale" value="True" data-bind="radiobuttonyesno:IsMale"/>
     </label>
     <label>Female
        <input type="radio" name="IsMale" value="False" data-bind="radiobuttonyesno:IsMale"/>
     </label>


답변

당신이 알아낼 일단 라디오 버튼의 초기 경기 만 문자열과 일치하고 싶어 하고 문자열로 값을 설정하고자, 단순히 문자열에 초기 값을 변환하는 문제이다.나는 Int 값으로 이것을 싸워야했다.

Observable을 설정 한 후 값을 문자열로 변환하면 KO가 거기에서 마법을 수행합니다. 개별 라인으로 매핑하는 경우 해당 라인에서 변환을 수행하십시오.

예제 코드에서는 Json을 사용하여 단일 명령으로 전체 모델을 매핑합니다. 그런 다음 Razor가 변환을 위해 따옴표 사이에 값을 삽입하도록합니다.

script type="text/javascript">
    KoSetup.ViewModel = ko.mapping.fromJS(@Html.Raw(Json.Encode(Model)));
    KoSetup.ViewModel.ManifestEntered("@Model.ManifestEntered");       //Bool
    KoSetup.ViewModel.OrderStatusID("@Model.OrderStatusID");           //Int
</script>

개발 중에 웹 페이지 하단에있는 “화면에 모두 덤프”를 사용합니다.

<h4>Debug</h4>
<pre data-bind="text: ko.toJSON($data, null, 2)"></pre>

다음은 데이터 값입니다. 이전

"OrderStatusID": 6,
"ManifestEntered": true,

그리고 이후

"OrderStatusID": "6",
"ManifestEntered": "True",

내 프로젝트에서는 같은 좌절감이없는 확인란을 사용할 수 있기 때문에 Bools를 변환 할 필요가 없었습니다.


답변

1과 0 대신 단순히 참과 거짓이 아닌 이유는 무엇입니까?

 <label>Male
    <input type="radio" name="IsMale" value="true" data-bind="checked:IsMale"/>
 </label>
 <label>Female
    <input type="radio" name="IsMale" value="false" data-bind="checked:IsMale"/>
 </label>


답변

익스텐더를 사용하여 더 많은 관찰 가능 항목에 쉽게 재사용 할 수 있습니다.

ko.extenders.boolForEditing = function (target, allowNull) {
    var result = ko.computed({
        read: function () {
            var current = target();
            var newValue = null;
            if (current === undefined || current === null || current === '') {
                if (!allowNull) {
                    newValue = 'false';
                }
            } else {
                newValue = current ? 'true' : 'false';
            }
            return newValue;
        },
        write: function (newValue) {
            var current = target();
            var valueToWrite = null;
            if (newValue === undefined || newValue === null || newValue === '') {
                if (!allowNull) {
                    valueToWrite = false;
                }
            } else {
                valueToWrite = newValue === 'true';
            }
            // only write if it changed
            if (valueToWrite !== current) {
                target(valueToWrite);
            } else {
                if (newValue !== current) {
                    target.notifySubscribers(valueToWrite);
                }
            }
        }
    }).extend({
        notify: 'always'
    });

    result(target());

    return result;
};

그런 다음 다음과 같이 사용하십시오.

this.IsMale.forEditing = this.IsMale.extend({boolForEditing: true});

제공되는 매개 변수 boolForEditing값이 널일 수 있는지 여부 표시하기 위해 입니다.

http://jsfiddle.net/G8qs9/1/ 참조