2016-04-07 42 views
10

Spero che qualcuno possa aiutarmi! Ho creato una direttiva che avvolge il plugin Jasny Bootstrap in modo più specifico con la maschera di input e tutto va bene!Vue js applica il filtro su v-model in un campo di input

Ora ho creato un filtro personalizzato supportato dal momento per formattare il campo della data!

Il formato di data che ricevo dall'applicazione back-end è YYY-MM-DD e devo mostrare sulla vista come GG/MM/AAAA ... Ho provato v-model="date | myDate" ma non ha funzionato correttamente!

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> 

V'è la JSBin se qualcuno è interessato!

Grazie in anticipo!

EDIT: Spiegando meglio quello che mi aspetto =)

Quando la pagina prima caricare l'ingresso ricevono il valore di 2015/06/26 e vorrei dimostrare che valore come GG/MM/AAAA così 26/06/2015! Funziona correttamente solo dopo aver iniziato a digitare qualcosa!

+0

"non ha funzionato correttamente" non è abbastanza descrittivo. Si prega di spiegare * come * non ha funzionato correttamente. Cosa ti aspettavi e cosa invece ha fatto? –

+0

Mi dispiace @MattJohnson! Ho appena aggiunto una spiegazione migliore in basso! Vedi se capisci per favore! –

+0

Nota che d/m/ye m/d/y sono ambigui, molto meglio usare il nome del mese come '10-apr-2016'. – RobG

risposta

8

Capisco cosa si sta provando a fare, tuttavia, a causa del legame bidirezionale quando si utilizza v-model, potrebbe essere meglio semplicemente formattare la data come lo si riceve dal server, e quindi, usarlo con il formato desiderato nell'app di front-end ('DD/MM/YYYY').

Quando si inviano i dati al back-end, è sufficiente formattarlo nuovamente nel formato server desiderato ('YYYY-MM-DD').

Nella tua Vue app, il flusso di lavoro sarebbe qualcosa di simile:

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

       //let's pretend the received date data was saved in a variable (serverDate) 
       //let's hardcode 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'); 
     } 

    } 

    }); 

Questo funziona bene per me, spero che aiuta.

Ecco un violino per esso:

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

+0

L'OP desidera "GG/MM/AAAA", non "MM/GG/AAAA" (anche se entrambi sono ambigui, utilizzare il nome del mese o l'abbreviazione sarebbe più chiaro). – RobG

+0

@RobG Grazie, l'ho appena modificato. Digita qui. Moment accetterà il suo formato desiderato finché sarà esplicito. La direttiva – crabbly

2

Quando si ottiene inizialmente il valore, regolarlo per adattarlo all'ingresso. Ho ottenuto che funziona nella funzione ready, ma si potrebbe fare questo dopo la chiamata DB così:

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

si può avere a che fare qualcosa di simile sulla via del ritorno fino al vostro database.

6

Ho avuto un problema simile quando ho voluto maiuscolo un valore di ingresso.

Questo è quello che ho finito per fare:

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

poi posso usare questa direttiva sul campo di input con un v-model.

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

Ora, ogni volta che si digita in questo campo o modificare someData, il valore si trasforma in maiuscolo.

Questo essenzialmente ha fatto la stessa cosa che speravo farebbe v-model="someData | uppercase". Ma certo, non puoi farlo.

In sommario: creare una direttiva che trasforma i dati, non un filtro.

+0

funziona quando la pagina è caricata o l'utente digita il testo. Quando l'interfaccia utente viene aggiornata a causa di modifiche in altri controlli, il metodo di aggiornamento sulla direttiva non verrà richiamato. Il valore nella casella di testo verrà ripristinato su uno non formattato. – flyfrog

+0

@flyfrog Penso che una scelta migliore qui sarebbe una proprietà 'computata' – james2doyle