Vue didn't show date Value - date

I am trying to get and modify a date value, I get the date value from mongoose, I correctly get the value, and I can modify it correctly, but moongoose give me the date in this format :
YYYY-MM-DDT00:00:00.000Z,
So I want to change the display value with an Italian format, like: DD/MM/YYYY.
I have try with this:
<template>
<div class="col">
<span> Date </span>
<input
:value="birth" v-on:input="birth = $event.target.value" type="date" />
</div>
</template>
<script>
import DataService from '#/services/DataService'
import ClickToEdit from '#/components/ClickToEdit'
import moment from 'moment'
export default {
name: 'Options',
data: function() {
return {
birth: '',
}
},
methods: {
async getAllInfo() {
var userInfo = await DataService.getInfoFromSomeWhere({
})
this.birth = this.frontEndDateFormat(userInfo.data.user[0].birth)
},
frontEndDateFormat: function(date) {
return moment(date, 'YYYY-MM-DDT00:00:00.000Z').format('DD/MM/YYYY')
}
},
mounted() {
this.getAllInfo()
}
}
</script>
The date was correctly changed, but the vue page didn't display the date value, and I think is because the default input value display the date in this way :
gg/mm/aaaa
I have already try to change the frontEndDateFormat method with gg/mm/aaaa instead of DD/MM/YYYY, but If I do this I have a strange value in input, like gg/00/amamamama ( I think the problem is related to moment).
So I tried to use :
<input :value="birth" v-on:input="birth = $event.target.value" type="date" v-model="date" />
But If I get an error:
:value="birth" conflicts with v-model on the same element because the
latter already expands to a value binding internally
What am I doing wrong? Thank you

Related

What is the best way to post form with multiple components using Vue js

as I'm on my Vue spree (started recently but so far I'm really enjoying learning this framework) couple of questions rised up. One of which is how to post form from multiple components. So before I continue forward I wanted to ask you what are you thinking about this way of structuring and point me in right direction if I'm wrong.
Here it goes.
I'm working on a SPA project using ASP.NET CORE 2.1 and Vue JS Template (with webpack)(https://github.com/MarkPieszak/aspnetcore-Vue-starter) and my project is structured in several containers, something like this:
In my app-root i registered several containers
<template>
<div id="app" class="container">
<app-first-container></app-first-container>
<app-second-container></app-second-container>
<!--<app-third-container></app-third-container>-->
<app-calculate-container></app-calculate-container>
<app-result-container></app-result-container>
</div>
</template>
<script>
// imported templates
import firstContainer from './first-container'
import secondContainer from './second-container'
import calculateContainer from './calculateButton-container'
//import thirdContainer from './third-container'
import resultContainer from './result-container'
export default {
components: {
'app-first-container': firstContainer,
'app-second-container': secondContainer,
// 'app-third-container': thirdContainer,
'app-calculate-container': calculateContainer,
'app-result-container': resultContainer
}
}
</script>
In my first container I'm having several dropdowns and two input fields with my script file where I'm fetching data from API and filling dropdowns and input fields with fetched data.
Something like this ( entered some dummy code for demonstration)
<template>
<div>
<h1>Crops table</h1>
<p>This component demonstrates fetching data from the server. {{dataMessage}}</p>
<div class="form-row">
<div class="form-group col-md-6">
<label for="exampleFormControlSelect1" class="col-form-label-sm font-weight-bold">1. Some text</label>
<select class="form-control" id="exampleFormControlSelect1" v-model="pickedCropType" #change="getCropsByType()">
<option v-for="(cropType, index) in cropTypes" :key="index" :value="cropType.id" :data-imagesrc="cropType.imgPath">{{ cropType.name }}</option>
</select>
</div>
<div class="form-group col-md-6">
<label for="exampleFormControlSelect2" class="col-form-label-sm font-weight-bold">2. Some text</label>
<select class="form-control" id="exampleFormControlSelect2">
<option v-for="(crop, index) in cropSelectList" :key="index" :value="crop.id">{{ crop.name }}</option>
</select>
</div>
</div>
</div>
</template>
<script>
import { mapActions, mapState } from 'vuex'
export default {
data() {
return {
cropTypes: null,
cropSelectList: null,
crops: null,
pickedCropType: null,
}
},
methods: {
loadPage: async function () {
try {
//Get crop types and create a new array with crop types with an added imgPath property
var cropTypesFinal = [];
let responseCropTypes = await this.$http.get(`http://localhost:8006/api/someData`);
responseCropTypes.data.data.forEach(function (element) {
cropTypesFinal.push(tmpType);
});
} catch (err) {
window.alert(err)
console.log(err)
}
},
getCropsByType: async function () {
//Get crops by crop type
let responseCrops = await this.$http.get(`http://localhost:8006/api/crop/Type/${this.pickedCropType}`);
var responseCropsData = responseCrops.data.data;
this.cropSelectList = responseCropsData;
}
},
async created() {
this.loadPage()
}
}
</script>
And in my second container I have different dropdowns and different input fields with different scripts etc.
So, my questions are:
1.) I'm having required data form field in first container and in second container I'm having additional data and my submit button is separated in third container (app-result-container). So, is this proper and logical way of structuring containers if not can you point me in right direction?
2.) Is it smart to input script tag in every container where I'm processing/fetching/submitting some data for that particular container? Should I put scripts tag in separated file and keep structure clean, separating html from js file.
Example:
import { something } from 'something'
export default {
data () {
return {
someData: 'Hello'
}
},
methods: {
consoleLogData: function (event) {
Console.log(this.someData)
}
}
}
3.) Can I send input values from one container to another (In my particular case from first and second container to app-calculate-container(third container))?
How to on submit return results container with calculated imported values
If you want components to communicate or share data with one another, you will need to either emit an event from one component up to the parent and pass it down via props, or use some kind of state management model, like Vuex, where each of your components can listen to the store.
Take a look at this code sandbox: https://codesandbox.io/s/8144oy7xy2
App.vue
<template>
<div id="app">
<child-input #input="updateName" />
<child-output :value="name" />
</div>
</template>
<script>
import ChildInput from "#/components/ChildInput.vue";
import ChildOutput from "#/components/ChildOutput.vue";
export default {
name: "App",
components: {
ChildInput,
ChildOutput
},
data() {
return {
name: ""
};
},
methods: {
updateName(e) {
this.name = e.target.value;
}
}
};
</script>
ChildInput.vue
<template>
<input type="text" #input="changeHandler">
</template>
<script>
export default {
name: "ChildInput",
methods: {
changeHandler(e) {
this.$emit("input", e);
}
}
};
</script>
ChildOutput.vue
<template>
<p>{{ value }}</p>
</template>
<script>
export default {
name: "ChildOutput",
props: {
value: {
type: String,
default: ""
}
}
};
</script>
What's going on?
The ChildInput component is a text field and on every change inside it, fires an event (emits using this.$emit() and passes the whole event up).
When this fires, App is listening to the change, which fires a method that updates the name data property.
Because name is a reactive data property and is being passed down as a prop to the ChildOutput component, the screen re-renders and is updated with the text written.
Neither ChildInput nor ChildOutput knows about one another. It's the parent that listens to the event passed to it, then passes the new prop down.
This way of working is fine and simple to understand, but I would strongly recommend looking at Vuex, as this method can get messy and complicated when you go beyond trivial tasks.

DatePicker date input with custom format

I want to stote dates in my state using redux-form. I use react-datepicker. To make the datepicker compatible with my redux-form i write:
import React, { PropTypes } from 'react';
import DatePicker from 'react-datepicker';
import moment from 'moment';
import 'react-datepicker/dist/react-datepicker.css';
const MyDatePicker = ({ input, meta: { touched, error } }) => (
<div>
<DatePicker
{...input} dateFormat="YYYY-MM-DD"
selected={input.value ? moment(input.value) : null}
/>
{
touched && error &&
<span className="error">
{error}
</span>
}
</div>
);
MyDatePicker.propTypes = {
input: PropTypes.shape().isRequired,
meta: PropTypes.shape().isRequired
};
export default MyDatePicker;
The problem is that when i choose date i want it to show as DD-MM-YYYY but i want the date to be saved in my state with the YYYY-MM-DD HH:MM:SS format. How to do this? I use the moment's format function but it did not seem to work
You should use the value lifecycle methods that redux-form provides for this.
Use parse to format the value coming from react-datepicker for storage and format to parse the value from the store back for react-datepicker to present it. Example:
function formatDateForInput(storedDate) {
// the returned value will be available as `input.value`
return moment(pickedDate).format('right format for your input')
}
function parseDateForStore(pickedDate) {
// the returned value will be stored in the redux store
return moment(storedDate).format('desired format for storage')
}
<Field
component={ MyDatePicker }
format={ formatDateForInput }
parse={ parseDateForStore }
/>
If this does not work for your, I would recommend checking if you need to put a custom onChange handler between the DatePicker and input prop provided by redux-form. Because it could be that the values DatePicker is using to call onChange are ones that redux-form does not understand. Like this:
const MyDatePicker = ({ input, meta: { touched, error } }) => {
const onChange = event => {
const pickedDate = event.path.to.value;
input.onChange(pickedDate);
}
return (
<div>
<DatePicker
dateFormat="YYYY-MM-DD"
selected={input.value ? moment(input.value) : null}
onChange={ onChange }
/>
{
touched && error &&
<span className="error">
{error}
</span>
}
</div>
);
}
MyDatePicker.propTypes = {
input: PropTypes.shape().isRequired,
meta: PropTypes.shape().isRequired
};
export default MyDatePicker;
Hope this helps!
If i am understanding correct you just need 2 different formats for same date one on UI and other to save ? moment(date).format('DD-MM-YYYY') and moment(date).format('YYYY-MM-DD HH:MM:SS') will give you both formats date.
Just use the prop dateFormat="dd/MM/yyyy"
Example :
<DatePicker
selected={startDate}
onChange={date => handleChange(date)}
dateFormat="DD/MM/YYYY"
/>
I used the below props -mask, inputFormat and format - to change the default format to "yyyy-MM-dd" format.
The format code "yyyy-MM-dd" is important, play around this to find the desired format.
Example:
<LocalizationProvider dateAdapter={AdapterDateFns} >
<DatePicker
label="SomeDate"
{...register("details_received_date")}
mask="____-__-__"
inputFormat="yyyy-MM-dd"
format="yyyy-MM-dd"
value={someDate}
onChange={(newValue) => {setSomeDate(newValue);}}
renderInput={(params) => <TextField {...params} />}
/>
</LocalizationProvider>
This will display in the front end and provide the value as well in the desired format.
Hope this helps.
Try this
inputFormat="DD/MM/YYYY"
const [value, setValue] = useState(null);
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DatePicker
label="DatePicker Example"
value={value}
onChange={(newValue) => {
setValue(newValue);
}}
renderInput={(params) => <TextField {...params} />}
inputFormat="DD/MM/YYYY"
/>
</LocalizationProvider>

Angular2 ngModel undefined with <input> tag

I'm using Angular2 and a forked version of Semantic-UI (that includes calendar module). I'm using calendar and dropdown features:
constructor() {
setTimeout(() => {
jQuery('.ui.dropdown').dropdown();
jQuery('.ui.calendar').calendar({ type: 'date' });
}, 1000);)
}
Here is my Plunker.
As you can see I can't get input from calendar selection.
I can't understand what could be the glitch. Can you figure out what could be the problem?
For some unknown reason [(ngModel)] is not getting updated.
But if its a matter of getting date only, you could use #templateVariable as shown here.
Working DEMO : https://plnkr.co/edit/X8Gjwzd62DvYN1S8jrFv?p=preview
Using #TemplateVariable
<input #date type="text" placeholder="Date">
<button (click)="test(date.value)">test</button>
test(date):void {
console.log(date);
console.log(this.name);
}
Using #ViewChild
#ViewChild('date') date:ElementRef;
test(date):void {
console.log(this.date.nativeElement.value);
console.log(date);
console.log(this.name);
}

Date from input field not being stored

I set up my Angular-Meteor application to allow users editing their date of birth. I am using bootstrap3-datepicker on the input field.
The input field in the form is defined like this:
<div class="form-group">
<label for="dateOfBirth" class="control-label">Date of Birth:</label>
<input type="date" id="dateOfBirth" class="form-control" ng-model="profileEdit.profile.dateOfBirth"/>
</div>
Picking and displaying the date works fine in the front-end, but the date is not stored when I save my form (all other data is). If a date exists before editing the record with the form, the date gets lost.
This is my controller:
class ProfileEdit {
constructor($stateParams, $scope, $reactive) {
'ngInject';
this.profile = Meteor.user().profile;
$('#dateOfBirth').datepicker({
format: "dd.mm.yyyy",
weekStart: 1,
startDate: "01.01.1940",
startView: 2
});
}
save() {
var profile = {
firstName: this.profile.firstName,
lastName: this.profile.lastName,
gender: this.profile.gender,
dateOfBirth: this.profile.dateOfBirth,
level: this.profile.level,
description: this.profile.description
}
Meteor.call('users.profile.update', profile, function(error, result) {
if(error){
console.log("error", error);
}
if(result) {
console.log('Changes saved!');
profile = {}
}
});
}
}
Logging profileEdit.profile.dateOfBirth to the console before saving the form data yields undefined.
It appears to me I am already losing the date between the form and my save() method. Why could this be?
I had the same issue with another datepicker, it appears that when a third party plugin updates the DOM, it does not update the modal that is attached to it. What I had to do was use the datepicker's events to catch the change and programatically update the field, IE:
$('.datepicker').datepicker()
.on('changeDate', function(e) {
// update your model here, e.date should have what you need
});
http://bootstrap-datepicker.readthedocs.io/en/latest/events.html

How do I use React and forms to get an array of checked checkbox values?

I am trying to build a filter for my portfolio website. Checkboxes that let you pick a technology (react, redux, jquery etc.) to display a piece of work(s) that contain(s) that/those technologies. So every time the user clicks on a box, I want to add the value (JavaScript, Redux, React etc.) to an array that I use in another function to check against my portfolio pieces and filter out what isn't there.
I am finding this very difficult and I think it should be quite simple. Can someone point me in the right direction? Is there a way to simply have a function trigger (onChange callback?) that reads the checked/unchecked status of my form input elements and then updates my state array accordingly? Can I get the status of all the checkboxes simply in React? Do I need to have individual state of checked/unchecked for my checkboxes?
It seems that jQuery makes it pretty possible with selectors with:
$('input[type="checkbox"]:checked').each(function () {}
If you don't care about the order and you just want to append the items to the array as they appear we could definitely do exactly what you suggest in your question. On the change event of the checkbox check if the box is checked or or unchecked (event.target.checked returns true if checked or false if unchecked) and handle the array logic accordingly. this is a simple representation of how that could work:
import React, { Component } from 'react'
import { connect } from 'react-redux'
class Portfolio extends Component {
constructor() {
super()
// initialize your options array on your state
this.state = {
options: []
}
}
onChange(e) {
// current array of options
const options = this.state.options
let index
// check if the check box is checked or unchecked
if (e.target.checked) {
// add the numerical value of the checkbox to options array
options.push(+e.target.value)
} else {
// or remove the value from the unchecked checkbox from the array
index = options.indexOf(+e.target.value)
options.splice(index, 1)
}
// update the state with the new array of options
this.setState({ options: options })
}
render() {
return (
<main className='portfolio'>
<form>
<div className="input-group">
<label>cb1</label>
<input type="checkbox" value={1} onChange={this.onChange.bind(this)} />
</div>
<div className="input-group">
<label>cb2</label>
<input type="checkbox" value={2} onChange={this.onChange.bind(this)} />
</div>
<div className="input-group">
<label>cb3</label>
<input type="checkbox" value={3} onChange={this.onChange.bind(this)} />
</div>
</form>
<div className="selected-items">
{this.state.options.map(number =>
<p key={number}>item: {number}</p>
)}
</div>
</main>
)
}
}
if you DO care about order, if you can append numerical values to the array like I did in this example you could easily give your checkboxes sorted numerical values and you could sort the array before updating your state so it's always in a certain order regardless of the order they are checked.
onChange(e) {
// current array of options
const options = this.state.options
let index
// check if the check box is checked or unchecked
if (e.target.checked) {
// add the numerical value of the checkbox to options array
options.push(+e.target.value)
} else {
// or remove the value from the unchecked checkbox from the array
index = options.indexOf(+e.target.value)
options.splice(index, 1)
}
// sort the array
options.sort()
// update the state with the new array of options
this.setState({ options: options })
}
Here's how I'm doing it:
// util.js
import getPath from 'lodash/get';
import setIn from 'lodash/fp/set';
export function linkMultiCheck(name, value) {
return {
checked: getPath(this.state, name, []).includes(value),
onChange: ev => {
let values = getPath(this.state, name, []);
if(ev.target.checked) {
values = [...values, value];
} else {
values = values.filter(v => v !== value);
}
this.setState(setIn(name, values));
},
}
}
// form.js
<ul>
{options.branches.map(branch => (
<li key={branch.id} className="checkbox">
<label>
<input type="checkbox" name={this.id} {...this::linkMultiCheck('formData.branchIds',branch.id)}/>
{branch.id}
</label>
</li>
))}
</ul>
i.e., if a checkbox is checked, append it to the current array of values. If it's unchecked, filter it out.
I'm using lodash here so that we can set deeply nested state values using dot notation.