In vuejs 2.6 app I use https://github.com/mengxiong10/vue2-datepicker/ with time select options :
<date-picker
v-model="hostelExtraDetails.reception_hours_start"
type="time"
:time-picker-options="timePickerOptions"
id="cbx_extra_details_reception_hours_start"
:lang="'en'"
:type="'time'"
:format="'hh:mm'"
:header="'HTRF'"
:placeholder="'Select time from picker'"
></date-picker>
import Vue from 'vue';
import moment from 'moment-timezone'
moment.tz.setDefault('Europe/Kiev')
import DatePicker from 'vue2-datepicker' // https://github.com/mengxiong10/vue2-datepicker
export default {
name: 'new',
components: {DatePicker}, // https://github.com/mengxiong10/vue2-datepicker
data() {
return {
...
timePickerOptions: {
start: '00:00',
step: '00:10',
end: '23:50'
},
loadData() {
this.hostelExtraDetails.reception_hours_start = // I need time value into valid datetime value
this.stringIntoDatetime("2019-04-17 " + response.data.hostelExtraDetails.reception_hours_start)
The thing is that selecting some time in picker I see 3 hours difference in model var.
I suppose that timezone is not set and which is the valid way setting timezone ?
2) as I need time value into valid datetime value I have a value like "2019-04-17T06:50:00.000Z", Which is simple way to get hours:minutes value from it ?
I found a decision in adding property:
<date-picker
valueType="format"
...
></date-picker>
and it works!
Related
I am getting my head around Vee-Validate next (v4) and how I might incorporate it in a Vue 3 project without loosing Vue's reactivity (i.e. not relying on the values simply being passed to the Form submit event).
By way of example, if I were making a hypothetical component which has autocomplete functionality, and sent a get request to the server once 3 letters had been typed, but for the input itself to be valid it required 8 letters, how would I get the value associated with the input?
using plain Vue, with pseudo-code something like:
defineComponent({
setup () {
const myVal = ref('')
const options = ref([])
watchEffect(() => if (myVal.value.length > 3) {
axios.get(...).then(serverVals => options.value = serverVals))
})
return { myVal, options }
how would I achieve this with vee-validate 4.x?
defineComponent({
setup () {
const schema = yup.object({ myVal: yup.string().required().min(8) })
// ???? what now to watch myVal
please note this is not about autocomplete - a range slider where I wanted a server call when the value was greater than 10 but a validation message if greater than 90 would also suffice as an example.
You could employ useField here to get a reactive value that's automatically watched.
const { value: myVal, errorMessage } = useField('myVal', undefined, {
initialValue: ''
});
const options = ref([])
watchEffect(() => if (myVal.value.length > 3) {
axios.get(...).then(serverVals => options.value = serverVals))
})
return { myVal, options }
Documentation has an example of using useField:
https://vee-validate.logaretm.com/v4/guide/composition-api#usefield()
Note that you don't have to use useForm, if you are using <Form> component and passing schema to it then that should work just fine.
I'm trying to build a custom filter component that takes a range from a text input control (e.g. '3-5') to filter the data. To do so I have modified the example given in the ag-grid documentation (see code below).
When changing the type in onFloatingFilterChanged() to 'equals', 'greaterThan', 'lessThan' etc. everything works fine. But with type 'inRange' no filtering is performed.
Working example can be found on Plunkr: https://plnkr.co/edit/oHWFIaHgWIDXP0P5
import { Component } from '#angular/core';
import {
IFloatingFilter,
IFloatingFilterParams,
NumberFilter,
NumberFilterModel,
} from '#ag-grid-community/all-modules';
import { AgFrameworkComponent } from '#ag-grid-community/angular';
export interface RangeFloatingFilterParams extends IFloatingFilterParams {
value: number;
}
#Component({
template: `
<input
type="text"
[(ngModel)]="currentValue"
(ngModelChange)="valueChanged()"
style="width: 70px;"
/>
`,
})
export class RangeFloatingFilter
implements IFloatingFilter, AgFrameworkComponent<RangeFloatingFilterParams> {
private params: RangeFloatingFilterParams;
public currentValue: string;
agInit(params: RangeFloatingFilterParams): void {
this.params = params;
this.currentValue = '';
}
valueChanged() {
let valueToUse = this.currentValue === 0 ? null : this.currentValue;
this.params.parentFilterInstance(function(instance) {
(<NumberFilter>instance).onFloatingFilterChanged(
'inRange',
valueToUse
);
});
}
onParentModelChanged(parentModel: NumberFilterModel): void {
if (!parentModel) {
this.currentValue = 0;
} else {
// note that the filter could be anything here, but our purposes we're assuming a greater than filter only,
// so just read off the value and use that
this.currentValue = parentModel.filter;
}
}
}
Faced the same issue with custom floating datepicker. I used setModelIntoUi method instead of onFloatingFilterChanged:
instance.setModelIntoUi({
type: 'inRange',
dateFrom: moment(value.min).format('YYYY-MM-DD'), // you have to use exactly this date format in order for it to work
dateTo: moment(value.max).format('YYYY-MM-DD'),
});
And in your case with numbers it'll be:
instance.setModelIntoUi({
type: 'inRange',
filter: value.min,
filterTo: value.max,
});
UPD: Added this line
instance.onUiChanged(true);
after the setModelIntoUi method, because of the bug: filter model wasn't updating on second use.
The code inside instance.onFloatingFilterChanged() only sets the first from value.
Use these lines below to get the correct result, as it is the only way to get inRange working.
instance.setTypeFromFloatingFilter('inRange');
instance.eValueFrom1.setValue(this._input1.value);
instance.eValueTo1.setValue(this._input2.value);
instance.onUiChanged(true);
Do you know how can I get the ordered list of field names from given form? Instance API has a property called "fieldList" and it's an array but it's not in correct order. (ordered list = [firstFieldName, secondFieldName, ...] so what I need is a list of field names in order they appear in my form - top to bottom)
Also the redux-form' action '##redux-form/REGISTER_FIELD' is dispatching out of correct form order so I guess it's not what I need here...
(My redux-form version: 7.3.0)
I have experience with redux-form and also have checked its API, but didn't find a documented way for getting the fields in the way they appear in the form.
However, here's how I would do it:
I'll create a Reducer, that will keep track of the fields in the order,
they are registered (appear in the form).
We have very detailed action. As you already mentioned - ##redux-form/REGISTER_FIELD action is dispatching out all the fields in process of being registered in the correct order. This action has the following payload:
{
type: '##redux-form/REGISTER_FIELD',
meta: {
form: 'user'
},
payload: {
name: 'firstName',
type: 'Field'
}
}
Create a reducer. So I'll just create a Reducer, that will listen for all ##redux-form/REGISTER_FIELD actions. Something like that:
// The reducer will keep track of all fields in the order they are registered by a form.
// For example: `user` form has two registered fields `firstName, lastName`:
// { user: ['firstName', 'lastName'] }
const formEnhancedReducer = (state = {}, action) {
switch (action.type) {
case '##redux-form/REGISTER_FIELD':
const form = action.meta.form
const field = action.payload.name
return { ...state, [form]: [...state[form], field] }
default:
return state
}
}
Usage. In order to get ordered fields by a form, you just have access the Store (state) formEnhancer property with the form name: state.formEnhanced.user.
Keep in mind that you have to consider some cases as ##redux-form/DESTROY, but I think it's a pretty straightforward implementation.
I would prefer to keep things simple and just subscribed to ##redux-form/REGISTER_FIELD and just change the reducer implementation a little bit, in order to prevent form fields duplication. So I will just validate if the form field is already registered and won't care for supporting ##redux-form/DESTROY.
Hope it helps.
One way that I have been able to retrieve an ordered list of form field names from a given form is via the registered fields stored in the redux form state using the connect HOC (Higher Order Component) from 'react-redux':
import React, { Component } from 'react';
import { connect } from 'react-redux';
import _ from 'lodash';
class Foo extends Component {
render() {
const {
registeredFields,
} = this.props;
...
...
...
}
}
const mapStateToProps = (state, props) => {
// retrieve the registered fields from the form that is stored in redux state; using lodash 'get' function
const registeredFields = _.get(state, 'form.nameOfYourForm.registeredFields');
// creating an object with the field name as the key and the position as the value
const registeredFieldPositions = _.chain(registeredFields).keys().reduce((registeredFieldPositions, key, index) => {
registeredFieldPositions[key] = index;
return registeredFieldPositions;
}, {}).value();
return({
registeredFieldPositions,
});
};
// registeredFieldPositions will now be passed as a prop to Foo
export default connect(mapStateToProps)(Foo);
Using Vue.js ( Vue-Tables https://www.npmjs.com/package/vue-tables ) with laravel.
The data is being succesfully displayed, but the daterangepicker (http://www.daterangepicker.com/) is not sorting at all.
No matter what interval I set, the records won't display. The field is being parsed with carbon to return in needed format
public function getFootageDateAttribute($date)
{
return Carbon::parse($date)->format('d-m-Y');
}
In the js file, I have dateFormat: "DD-MM-YY", filterByColumn: true, dateColumns: ['footage_date'], . When I inspect with vue dev-tools, the field is footage_date: "03-04-2016"
If I hardcode the date as in the example ( https://jsfiddle.net/matfish2/f5h8xwgn/ ) using
// Courtesy of Tomasz Nurkiewicz (Elegant method to generate array of random dates within two dates)
function randomDate(start, end) {
return moment(start.getTime() + Math.random() * (end.getTime() - start.getTime()));
}
the date is in this format footage_date: "1974-03-27T18:19:40.364Z" and it works.
Pastebin of the full js file http://pastebin.com/6hCe2eQL . Client side http://pastebin.com/xTUcAK98
The footage_date was supposed to be passed as a moment instance, not as a date string, therefore, modifying the ready function did it
ready: function(){
this.$http.get('/api/footage')
.then(function(response){
footages = response.data
footages.forEach(footage => {
footage.footage_date = moment(footage.footage_date)
})
this.tableData = footages
}.bind(this))
}
All my dates come formatted as ISO 8601 from the backend, eg 2014-01-01T12:45:30Z. Across the application, I want to display them in different formats...
shorthand in tables, eg Jan 1
longer, more explicit format on a detailed view, eg Monday, January 1st.
Solution I made a helper where I can pass in the format. Easy enough.
can.mustache.registerHelper('formatDate', function(date, format) {
return date() ? moment(date()).format(format) : '-';
});
Problem Now I'm implementing the bootstrap datepicker, how can I capture these requirements...
the date in my model is formatted as ISO
bind to input with can-value in template
display format MM/DD/YY for users and datepicker
Bonus points if I don't need to make a compute for every single date value in my models, as they're quite large and with many dates.
Unfortunately there isn't a nice API for this(yet). However, you can achieve custom formats in a view while keeping your model properties pristine with the below code.
can.view.attr('can-somecustom-value', function(el, data) {
var attr = el.getAttribute('can-somecustom-value'),
value = data.scope.computeData(attr, {
args: []
}).compute;
new FormattedValue(el, {
value: value
//value is the only one we really care about, but
//you could specify other arbitrary options here
//such as "format: 'MM/DD/YYYY' to be used in your __format methods below"
});
});
var FormattedValue = can.Control.extend({
init: function () {
this.set();
},
__format: function() {
// return formatted version of this.options.value;
},
__deformat: function() {
// return this.element[0].value sans format(keeps your model pristine);
},
'{value} change': 'set',
set: function () {
if (!this.element) {
return;
}
var self = this;
setTimeout(function() {
self.element[0].value = self.__format();
});
},
'change': function () {
if (!this.element) {
return;
}
this.options.value(this.__deformat());
}
});
This will allow you to do the following:
<input can-somecustome-value="myDateProp"/>
where "myDateProp" is an attribute on some can.Map/can.Model/etc.
This will result in the input displaying a custom string format, while someModel.attr('myDateProp') will still return the ISO format(which in turn means the ISO format will also be saved to the server).
There is some internal discussion regarding adding filters/parsers to allow control over formats specific only to view rendering.