Vue js применяет фильтр к v-модели в поле ввода

Надеюсь, кто-то может мне помочь! Я сделал директиву, вставляя Jasny Bootstrap Plugin более конкретно в маску ввода-маски, и все идет хорошо!

Теперь я создал настраиваемый фильтр, поддерживаемый моментом, чтобы отформатировать поле даты!

Формат даты, который я получаю от моего бэкэнд-приложения, - это YYY-MM-DD, и я должен показать его в виде DD/MM/YYYY... Я пробовал v-model="date | myDate", но это не сработало!

JS

Vue.directive('input-mask', {
  params: ['mask'],

  bind: function() {
    $(this.el).inputmask({
      mask: this.params.mask
    });

  },
});

Vue.filter('my-date', function(value, formatString) {

  if (value != undefined)
    return '';

  if (formatString != undefined)
    return moment(value).format(formatString);

  return moment(value).format('DD/MM/YYYY');

});

var vm = new Vue({
  el: 'body',
  data: {
    date: '2015-06-26',
  }
});

HTML

<label>Date</label>
<input type="text" class="form-control" v-input-mask mask="99/99/9999" v-model="date">
<p>{{ date | myDate 'dd/mm/yyyy' }}</p>

Существует JSBin, если кто-то заинтересован!

Спасибо заранее!

РЕДАКТИРОВАТЬ: лучше объяснять, что я ожидаю =)

Когда на первой странице загрузки вход получает значение 2015-06-26, и я хотел бы показать это значение как DD/MM/YYYY, так 26/06/2015! Он работает правильно только после того, как я начну вводить что-то!

Ответ 1

Я понимаю, что вы пытаетесь сделать, однако из-за двухстороннего связывания при использовании v-модели может быть лучше просто отформатировать дату, когда вы получаете ее с сервера, а затем использовать ее в нужном формате в ваше внешнее приложение ('DD/MM/YYYY').

Отправляя данные обратно на сервер, вы просто форматируете их обратно в нужный формат сервера ('YYYY-MM-DD').

В вашем приложении Vue рабочий процесс будет выглядеть примерно так:

 new Vue({
    el: 'body',
    data: {
      date: null,
    },
    methods: {
        getDataFromServer: function() {
                // Ajax call to get data from server

                // Let pretend the received date data was saved in a variable (serverDate)
                // We will hardcode it for this ex.
                var serverDate = '2015-06-26';

                // Format it and save to vue data property
                this.date = this.frontEndDateFormat(serverDate);
        },
        saveDataToServer: function() {
            // Format data first before sending it back to server
            var serverDate = this.backEndDateFormat(this.date);

            // Ajax call sending formatted data (serverDate)
        },
        frontEndDateFormat: function(date) {
            return moment(date, 'YYYY-MM-DD').format('DD/MM/YYYY');
        },
        backEndDateFormat: function(date) {
            return moment(date, 'DD/MM/YYYY').format('YYYY-MM-DD');
        }
    }
  });

Это хорошо работает для меня, надеюсь, это поможет.

Вот скрипка для этого:

https://jsfiddle.net/crabbly/xoLwkog9/

Синтаксис ОБНОВЛЕНИЕ:

    ...
    methods: {
        getDataFromServer() {
                // Ajax call to get data from server

                // Let pretend the received date data was saved in a variable (serverDate)
                // We will hardcode it for this ex.
                const serverDate = '2015-06-26'

                // Format it and save to vue data property
                this.date = this.frontEndDateFormat(serverDate)
        },
        saveDataToServer() {
            // Format data first before sending it back to server
            const serverDate = this.backEndDateFormat(this.date)

            // Ajax call sending formatted data (serverDate)
        },
        frontEndDateFormat(date) {
            return moment(date, 'YYYY-MM-DD').format('DD/MM/YYYY')
        },
        backEndDateFormat(date) {
            return moment(date, 'DD/MM/YYYY').format('YYYY-MM-DD')
        }
    }
  })

Ответ 2

У меня была аналогичная проблема, когда я хотел загладить введенное значение.

Вот что я сделал:

// create a directive to transform the model value
Vue.directive('uppercase', {
  twoWay: true, // this transformation applies back to the vm
  bind: function () {
    this.handler = function () {
      this.set(this.el.value.toUpperCase());
    }.bind(this);
    this.el.addEventListener('input', this.handler);
  },
  unbind: function () {
    this.el.removeEventListener('input', this.handler);
  }
});

Тогда я могу использовать эту директиву в поле ввода с v-model.

<input type="text" v-model="someData" v-uppercase="someData">

Теперь, всякий раз, когда я ввожу в это поле или изменяю someData, значение преобразуется в верхний регистр.

Это по существу делало то же самое, что я надеялся v-model="someData | uppercase". Но, конечно, вы не можете этого сделать.

В суммировании: создайте директиву, которая преобразует данные, а не фильтр.

Ответ 3

Когда вы сначала получите значение, отрегулируйте его, чтобы он соответствовал входу. Я получил его в функции ready, но вы могли бы это сделать и после вызова БД:

ready: function(){    
  var year = this.date.substr(0, 4);
  var monDay = this.date.substr(5,5);
  var result = monDay + "-" + year;
  this.date = result.replace(/-/g,"/");
}

Возможно, вам придется сделать что-то подобное по пути обратно в вашу базу данных.

Ответ 4

Вот как я реализовал фильтр vue для v-модели, используя обратный вызов watch, это не будет обновлять значение при загрузке.

Vue.filter('uppercase', function (value) {
    return value.toUpperCase();
});

HTML:

<input type="text" v-model="someData">

И обратный вызов часов:

watch:{
   someData(val) {
       this.someData = this.$options.filters.uppercase(val);
    },
}

Ответ 5

Перейдите в main.js и добавьте следующий код:

import moment from 'moment'
Vue.filter('myDate', function (value) {
    if (value) {
        return moment(String(value)).format('dd/mm/yyyy')
    }
});

В своем HTML сделайте следующее:

<label>Date</label>
<v-text-field :value="date | myDate" @input="value=>date=value"></v-text-field>
<p>{{ date | myDate 'dd/mm/yyyy' }}</p>

Итак, мы использовали выше v-bind, чтобы связать значение и обработчик события @input, чтобы иметь функциональность v-модели.

Ответ 6

Я обнаружил, что могу фильтровать ввод, используя обычный компонент v-bind:value/v-on:input dance, не прибегая к $forceUpdate() data или watch если я просто вызываю $forceUpdate() после $forceUpdate() отфильтрованного значения:

Компонент Vue:

{
  props: ['value'],
  methods: {
    mEmit: function(EVT) {
      const VAL      = EVT.target.value;
      var   FILTERED = myFilterFunction(VAL);
      this.$emit('input', FILTERED);
      this.$forceUpdate();
    }
  }
}

Компонент HTML (данные фильтруются по мере ввода):

  <input type="text" v-bind:value="value" v-on:input="mEmit($event)" />

Используя компонент:

<my-component v-model="myDataVar"></my-component>