programing

Vue에서 라디오 버튼을 확인하는 방법v-model을 사용하지 않는 JS 2

sourcejob 2022. 10. 4. 23:27
반응형

Vue에서 라디오 버튼을 확인하는 방법v-model을 사용하지 않는 JS 2

Vue에서 라디오 버튼 목록의 체크된 값을 설정하려고 합니다.JS 2. 여기서 기존 기사를 검토하고 몇 가지 다른 수동 접근 방식을 시도했지만 전혀 작동하지 않습니다.

폼 빌더가 사용하는 사용자 지정 라디오 버튼 목록 컨트롤을 작업 중이기 때문에 여기서는 v-model을 사용하지 않습니다.이 문제는 nullable 부울을 처리하기 위해 네스트된 라디오 버튼 목록을 맨 위에 작성하고 있기 때문에 더욱 복잡합니다.그 복잡성은 제쳐두고, 제 무선 컴포넌트는 이렇게 생겼습니다.

<template>
  <div class="form__radio-list">
    <span class="form__radio-list__intro">{{ introText }}</span>
    <ul class="form__radio-list__options">
      <li v-for="item in options"
          :key="item.key ? item.key : item"
          class="form__radio-list__options__item">
        <input type="radio"
               :id="item.key ? item.key.toKebabCase() : item.toKebabCase()"
               :name="def"
               :value="item.value != undefined ? item.value : item"
               :disabled="disabled"
               :checked="isChecked(item)"
               @input="onInput"
               @change="$emit('change', $event.target.checked)">
        <label :for="item.key ? item.key : item">{{ item.text ? item.text : item }}</label>
      </li>
    </ul>
  </div>
</template>

<script>

export default {

    props: {
        def: {
            type: String,
            required: true
        },
        introText: {
            type: String,
            default: ''
        },
        options: {
            type: Array,
            required: true
        },
        initialValue: {
            type: [String, Number, Boolean],
            default: null
        },
        disabled: {
            type: Boolean,
            default: false
        }
    },

    data() {
        return {
            value: this.initialValue
        }
    },

    methods: {

        _parseValue() {
            return this.value ? parseInt(this.value) : null
        },

        isChecked(item) {
            const checked = item.value === this.value || item === this.value || item.value == this._parseValue()
            this.$logger.logObject({ item, parentValue: this.value, checked }, 'Checking value for an item')
            return checked
        },

        onInput($event) {
            this.value = $event.target.checked
            this.$emit('input', $event.target.checked)
        }
    }
}

</script>

로그를 보면 '체크' 값이 올바르게 설정되어 있어야 합니다(그렇지 않습니다).

또한 입력 태그를 'v-if' 문으로 분할하여 선택한 매개 변수 집합과 없는 매개 변수(이러한 느낌이 들었지만)가 있고 HTML 관점에서 작동(예상대로 "체크 표시"됨)하는 방법을 사용하려고 했지만 브라우저에서는 두 가지 옵션이 모두 선택되지 않았습니다.

다음과 같은 부울 컴포넌트 리너러를 통해 컴포넌트를 소비하고 있습니다.

<template>
  <hh-radio class="form__radio-list--yes-no"
            :def="def"
            :intro-text="introText"
            :options="options"
            :initial-value="initialValue"
            :disabled="disabled"
            @change="$emit('change', $event)"
            @input="$emit('input', $event)" />
</template>

<script>

export default {

    props: {
        def: {
            type: String,
            required: true
        },
        introText: {
            type: String,
            default: ''
        },
        initialValue: {
            type: [String, Boolean],
            default: null
        },
        disabled: {
            type: Boolean,
            default: false
        }
    },

    computed: {

        options() {
            return [{
                key: 'yes',
                text: 'Yes',
                value: true
            }, {
                key: 'no',
                text: 'No',
                value: false
            }]
        }
    }
}

</script>

그리고 이것은 결국 다음과 같은 형태로 소비됩니다.

  <hh-yes-no class="editable-segment-field__bool"
             :def="pvc-enabled"
             :initial-value="pvc.value"
             @input="onInput" />

값 패스스루는 정상적으로 동작하고 있는 것 같습니다.중요한 문제는 기존 데이터에서 현재 선택된 항목을 특정하지 않는다는 것입니다.

나는 여기서 제안을 시도했다 - Vue.v-model 및 여기 없는 JS 무선 입력 - Vue.v-model이 없는 JS 확인란에서 큰 성공을 거두지 못했습니다.

아래 예제를 사용하여 가능한 한 컴포넌트의 동적 요소를 추가하여 문제의 근원을 파악하려고 했습니다.

이렇게 단순한 컴포넌트를 갖게 되었습니다.

<template>
  <div :class="`form__radio-list ${(this.def ? `form__radio-list--${this.def} js-${this.def}` : '' )}`">
    <span class="form__radio-list__intro">{{ introText }}</span>
    <ul class="form__radio-list__options">
      <li class="form__radio-list__options__item">
        <input id="awesome"
               type="radio"
               name="isawesome"
               :checked="radio === 'Awesome'"
               value="Awesome"
               @change="radio = $event.target.value">
        <label for="awesome">Awesome</label>
      </li>
      <li class="form__radio-list__options__item">
        <input id="super"
               type="radio"
               name="isawesome"
               :checked="radio === 'Super Awesome'"
               value="Super Awesome"
               @change="radio = $event.target.value">
        <label for="super">Super</label>
      </li>
    </ul>
    <span>Selected: {{ value }} | {{ radio }}</span>
  </div>
</template>

<script>

export default {

    props: {
        def: {
            type: String,
            required: true
        },
        introText: {
            type: String,
            default: ''
        },
        initialValue: {
            type: [String, Boolean],
            default: null
        },
        disabled: {
            type: Boolean,
            default: false
        }
    },

    // delete this
    data() {
        return {
            value: this.initialValue,
            radio: 'Awesome'
        }
    },

    computed: {

        options() {
            return [{
                key: 'yes',
                text: 'Yes',
                value: true
            }, {
                key: 'no',
                text: 'No',
                value: false
            }]
        }
    }
}

</script>

추가하자마자 실패했어요.name="isawesome"라디오 버튼 항목에 액세스합니다.'이름'을 소개하면 뭔가 잘못되는 것 같아요.여러 개의 라디오 버튼 목록이 상호 작용하는 것을 방지하기 위해 반드시 '이름'이 필요합니다.아니면 Vue가 제가 몰랐던 작업을 처리하고 있는 것입니까?

다음으로 작업 예를 제시하겠습니다.

new Vue({
  el: "#app",
  data: {
   radio: 'Awesome'
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <span>Vue is:</span> <br>

  <label>Awesome
  <input 
    type="radio"
    :checked="radio === 'Awesome'" 
    value="Awesome"
    @change="radio = $event.target.value"
  >
  </label>
  
   <label>Super Awesome
  <input 
    type="radio" 
    :checked="radio === 'Super Awesome'"
    value="Super Awesome"
    @change="radio = $event.target.value"
  >
  </label>
  
  <hr>
  
  <span>Selected: {{radio}}</span>
</div>

이것은 Vue.js의 버그/이상함인 것 같습니다.Roli Roli의 예를 사용하여 나는 그의 예와 나의 요구를 모두 들어 중간에서 만날 때까지 계속 조정할 수 있었고, 그래서 나는 제거 과정을 통해 문제를 발견할 수 있었다.

다음은 두 요소가 함께 포함된 구성 요소의 복사본입니다.@birdspider가 위에서 언급했듯이 HTML에서는 동작하지 않을 것입니다.그러나 Vue에서는 동작합니다.

<template>
  <div :class="`form__radio-list ${(this.def ? `form__radio-list--${this.def} js-${this.def}` : '' )}`">
    <span class="form__radio-list__intro">{{ introText }}</span>
    <ul class="form__radio-list__options">
      <li class="form__radio-list__options__item">
        <input id="yes"
               type="radio"
               :checked="value === true"
               :value="true"
               @change="value = $event.target.value">
        <label for="yes">Yes</label>
      </li>
      <li class="form__radio-list__options__item">
        <input id="no"
               type="radio"
               :checked="value === false"
               :value="false"
               @change="value = $event.target.value">
        <label for="no">No</label>
      </li>
      <li class="form__radio-list__options__item">
        <input id="awesome"
               type="radio"
               :checked="radio === 'Awesome'"
               value="Awesome"
               @change="radio = $event.target.value">
        <label for="awesome">Awesome</label>
      </li>
      <li class="form__radio-list__options__item">
        <input id="super"
               type="radio"
               :checked="radio === 'Super Awesome'"
               value="Super Awesome"
               @change="radio = $event.target.value">
        <label for="super">Super</label>
      </li>
    </ul>
    <span>Selected: {{ value }} | {{ radio }}</span>
  </div>
</template>

<script>

export default {

    props: {
        def: {
            type: String,
            required: true
        },
        introText: {
            type: String,
            default: ''
        },
        initialValue: {
            type: [String, Boolean],
            default: null
        },
        disabled: {
            type: Boolean,
            default: false
        }
    },

    data() {
        return {
            value: this.initialValue,
            radio: 'Awesome'
        }
    }
}

</script>

이것은 완전히 정상적으로 동작하며, 2개의 개별 라디오 버튼 리스트로 렌더링됩니다.하나는 예스/아니오, 이제1개는 어썸/슈퍼 어썸입니다.무선 입력에 'name' 태그를 추가하려고 하면 라디오 버튼 그룹에서 선택된 상태가 전혀 설정되지 않습니다.

----갱신 ----

이는 '이름'을 추가하려는 시도가 Vue에 의해 무시되어야 하는 버그처럼 보이지만 그렇지 않습니다.단, ES5 스타일의 컴포넌트를 codepen으로 작성하는 경우는 해당되지 않습니다(이 때문에 codepen으로 재평가할 수 없습니다).

ES6 스타일 파일을 사용하면 이 컴포넌트는 체크된 값을 설정하지 않습니다(이 단순화된 예의 절반은 @birdspider로 크레딧).

<template>
  <div>
    <ul class="form__radio-list__options">
      <li class="form__radio-list__options__item">
        <input id="awesome" type="radio" name="isawesome"
               :checked="radio === 'Awesome'"
               value="Awesome"
               @change="onChange($event.target.value)">
        <label for="awesome">Awesome</label>
      </li>
      <li class="form__radio-list__options__item">
        <input id="super" type="radio" name="isawesome"
               :checked="radio === 'Super Awesome'"
               value="Super Awesome"
               @change="onChange($event.target.value)">
        <label for="super">Super</label>
      </li>
    </ul>
    <ul class="form__radio-list__options">
      <li class="form__radio-list__options__item">
        <input id="awesome" type="radio" name="other"
               :checked="radio2 === 'other'"
               value="other"
               @change="onChange2($event.target.value)">
        <label for="awesome">other</label>
      </li>
      <li class="form__radio-list__options__item">
        <input id="super" type="radio" name="other"
               :checked="radio2 === 'another'"
               value="another"
               @change="onChange2($event.target.value)">
        <label for="super">another</label>
      </li>
    </ul>
  </div>
</template>

<script>

export default {

    data() {
        return {
            radio: 'Awesome',
            radio2: 'another'
        }
    },

    methods: {

        onChange(e) {
            this.radio = e
        },
        onChange2(e) {
            this.radio2 = e
        }
    }
}

</script>

(누군가 Codepen이나 JS Fielle에서 어떻게 실행할 수 있는지 알려주시면 감사하겠습니다!)

이름 속성을 삭제하면 동작합니다.

컴포넌트 파일이 아닌 단일 Vue 인스턴스로 Codepen에 기본적으로 동일한 내용을 넣는 경우 그것도 작동합니다.

언급URL : https://stackoverflow.com/questions/57458819/how-to-check-a-radio-button-in-vue-js-2-without-using-v-model

반응형