Текстовое поле Vuetify: изменения значений не сохраняются (теряется при размытии или фокусе) - PullRequest
3 голосов
/ 15 января 2020

Вот мой код. Смотрите тег <v-text-field>. При событии keypress оно перехватывает и преобразует введенное значение во что-то еще, если текстовое поле заполнено (вставьте символ нажатия клавиши в курсор и вставьте pu sh остальные символы в последующие поля ввода).

Вход обновляется с правильными значениями сначала, НО, когда я размываю его (фокус), он возвращается к значению, которое было до события keypress. Кроме того, дополнительный символ правильно добавляется в последующее поле ввода, но его значение не сохраняется - оно изменяется в фокусе.

Я не написал ни одного обработчика событий, который бы делал это. Я попытался удалить <v-form> и атрибут :rules.

Я также попытался связать каждый <v-text-field> с v-model и назначить новое входное значение для модели (двухуровневый массив) и когда я проверяю его в Vue Devtools, я замечаю, что он не обновляет значение, пока не сделаю размытие / фокус. Обновленные значения также кажутся ненадежными.

Я пытался вызвать change, даже keyup, после установки входного значения, но безрезультатно.

Я пытался не JQuery способ установки входного значения, без разницы.

Пробовал с или без event.preventDefault() в обработчике keypress, без разницы.

Пробовал keyup вместо из keypress просто чтобы посмотреть поведение (мне нужно keyup), но та же проблема.

** ОБНОВЛЕНИЕ: также попытался удалить все v-model с, без разницы.

Vuetify версия: 1.5.17.

Что может быть причиной этого? Пожалуйста помоги! Я обещаю, что заплачу это вперед и помогу другим здесь, когда у меня есть права ответа! Каждый маленький намек очень поможет!

            <v-stepper
                    v-model="stepperStep"
            >
                <v-stepper-items>
                    <v-form autocomplete="off"
                            ref="form"
                            v-model="valid"
                            lazy-validation >
                        <v-stepper-content
                                v-for="n in numLines"
                                :key="`${n}-content`"
                                :step="n"
                        >
                            <div v-show="false" :id="`wordLine_`+(n-1)" :data-numWords="wordLines[n-1].length" class="wordLine" style="display:flex; justify-content:center; margin:0 0 25px;">
                                <div v-for="(wordSize, key2) in wordLines[n-1]">
                                    <div class="wordBox" style="display:flex; color:#f00;">
                                        <v-text-field required class="wordInput" data-isWordInput="1" :stepperStep="n" :rel="key2" :rules="requiredRule" outline single-line dense height="36" @click:clear="wordInputCleared(n-1, key2)" :size="wordSize" :maxlength="wordSize"></v-text-field>
                                    </div>
                                </div>
                            </div>
                        </v-stepper-content>
                    </v-form>
                </v-stepper-items>
                <v-stepper-header v-show="numLines > 1">
                    <template v-for="n in numLines">
                        <v-stepper-step
                                :key="`${n}-step`"
                                :complete="stepperStep == n"
                                :step="n"
                                :editable="true"
                        >
                        </v-stepper-step>
                    </template>
                </v-stepper-header>
            </v-stepper>

Под mounted():

        $(document).on('keypress', '.wordInput input[type="text"]', function(event) {
            if (event.keyCode == 32) { event.preventDefault(); return; }
            if (event.keyCode == 37 || event.keyCode == 39 || event.keyCode == 9 || event.keyCode == 16) return; // arrow keys, tab, shift

            let sizeRemaining = $(this).attr('maxlength') - $(this).val().length;

            let selectedText = $(this)[0].value.slice($(this)[0].selectionStart, $(this)[0].selectionEnd);
            if (selectedText.length > 0) return;    // if text is selected, we want this triggered keystroke to replace the selection (default behavior), not auto-advance

            let cursorAtLastPosition = ($(this)[0].selectionEnd == $(this).attr('maxlength'));

            if (event.keyCode != 8 && event.keyCode != 46) {
                if (sizeRemaining == 0) {
                    event.preventDefault();

                    let keyVal = event.key;
                    let lastCharBeforeDisplaced = $(this).val().charAt($(this).val().length-1);

                    if (cursorAtLastPosition) {
                        if (parseInt($(this).attr('rel'))+1 == $(this).closest('.wordLine').attr('data-numWords')) {    // last wordbox
                            if (_this.stepperStep == _this.numLines) {  // last/only line
                                $('#btnFinished').focus(); return;
                            }
                        } else {
                            let $nextWord = $(this).closest('.wordLine').find('.wordInput').find('input[type="text"][rel="'+(parseInt($(this).attr('rel'))+1)+'"]');
                            lastCharBeforeDisplaced = keyVal;
                        }
                    } else {    // insert keyVal at cursor
                        let lastCharRemoved = $(this).val().slice(0, -1);

                        $(this).val(lastCharRemoved.slice(0, $(this)[0].selectionEnd) + keyVal + lastCharRemoved.slice($(this)[0].selectionEnd));
                    }

                    _this.cascadeInsertNextWordbox($(this), lastCharBeforeDisplaced);
                }
            }
        });

Под methods:

        cascadeInsertNextWordbox($currentWordbox, displacedChar) {
            let $nextWordbox = this.getNextWordbox($currentWordbox);
            if ($nextWordbox.length) {  // exists
                if ($nextWordbox.val().length == $nextWordbox.attr('maxlength')) {      // is full
                    let lastCharBeforeDisplaced = $nextWordbox.val().charAt($nextWordbox.val().length-1);
                    $nextWordbox.val($currentWordbox.val().slice(0, -1));   // remove last char
                    this.cascadeInsertNextWordbox($nextWordbox, lastCharBeforeDisplaced);
                }
            }
            $nextWordbox.val(displacedChar + $nextWordbox.val());
        },

1 Ответ

1 голос
/ 16 января 2020

Нашли решение по этой ссылке ! $ forceUpdate () - это то, что было нужно. Обновление через v-модель:

                            <div v-show="false" :id="`wordLine_`+(n-1)" :data-numWords="wordLines[n-1].length" class="wordLine" style="display:flex; justify-content:center; margin:0 0 25px;">
                                <div v-for="(wordSize, key2) in wordLines[n-1]">
                                    <div class="wordBox" style="display:flex; color:#f00;">
                                        <v-text-field v-model="wordInputs[n-1][key2]" required class="wordInput" data-isWordInput="1" :stepperStep="n" :rel="key2" :rules="requiredRule" outline single-line dense height="36" @click:clear="wordInputCleared(n-1, key2)" :size="wordSize" :maxlength="wordSize"></v-text-field>
                                        <div v-show="false" class="wordInputSizeRemaining" style="margin:4px 0px 0px 6px;">{{wordSize}}</div>
                                    </div>
                                </div>
                            </div>

И:

                    } else {    // insert keyVal at cursor
                        let lastCharRemoved = $(this).val().slice(0, -1);
                        _this.wordInputs[$(this).attr('stepperstep')-1][$(this).attr('rel')] = lastCharRemoved.slice(0, $(this)[0].selectionEnd) + keyVal + lastCharRemoved.slice($(this)[0].selectionEnd);
                        _this.$forceUpdate();
                    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...