web-dev-qa-db-fra.com

Vue js applique un filtre sur v-model dans un champ de saisie

J'espère que quelqu'un pourra m'aider! J'ai créé une directive qui englobe le plug-in Jasny Bootstrap, plus spécifiquement le masque de saisie et tout se passe bien!

Maintenant, j'ai créé un filtre personnalisé supporté par moment pour formater le champ de date!

Le format de date que je reçois de mon application dorsale est AAAA-MM-JJ et je dois afficher JJ/MM/AAAA sur la vue ... J'ai essayé v-model="date | myDate" mais cela n'a pas fonctionné correctement!

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>

Il y a le JSBin si quelqu'un est intéressé!

Merci d'avance!

EDIT: Expliquant mieux ce à quoi je m'attends =)

Lors du premier chargement de la page, l'entrée reçoit la valeur du 26/06/2015 et j'aimerais afficher cette valeur sous la forme JJ/MM/AAAA afin que le 26/06/2015! Cela fonctionne correctement seulement après que je commence à taper quelque chose!

16
Gustavo Bissolli

Je comprends ce que vous essayez de faire, cependant, en raison de la liaison bidirectionnelle lors de l’utilisation de v-model, il peut être préférable de simplement formater la date telle que vous la recevez du serveur, puis de l’utiliser avec le format souhaité. votre application front-end ('DD/MM/YYYY'). 

Lorsque vous renvoyez les données au back-end, il vous suffit de les formater au format de serveur souhaité ('YYYY-MM-DD').

Dans votre application Vue, le flux de travail ressemblerait à ceci:

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

                // Let's 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');
        }
    }
  });

Cela fonctionne bien pour moi, espérons que cela aide.

Voici un violon pour ça:

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

Syntaxe UPDATE:

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

                // Let's 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')
        }
    }
  })
11
crabbly

J'ai eu un problème similaire quand je voulais mettre une valeur d'entrée en majuscule.

C'est ce que j'ai fini par faire:

// 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);
  }
});

Ensuite, je peux utiliser cette directive sur le champ de saisie avec un v-model.

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

Maintenant, chaque fois que je tape dans ce champ ou que je change someData, la valeur est transformée en majuscule.

Cela a essentiellement fait la même chose que j'espérais que v-model="someData | uppercase" ferait. Mais bien sûr, vous ne pouvez pas faire ça.

En résumé: crée une directive qui transforme les données, pas un filtre .

8
james2doyle

Lorsque vous obtenez la valeur initialement, ajustez-la pour l'adapter à l'entrée. Je l’ai obtenu avec la fonction ready, mais vous pouvez le faire aussi après votre appel à la base de données:

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,"/");
}

Vous devrez peut-être faire quelque chose de similaire en remontant dans votre base de données.

2
Jeff

Voici comment j'ai mis en place un filtre de vue pour un v-modèle utilisant le rappel de la montre, cela ne mettra pas à jour la valeur au chargement.

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

Le html:

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

Et le rappel de la montre:

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