Angular material datepicker get value as string - angular8

I have an Angular Material datepicker. I have formatted the date as I wish but now I can't figure out how to send the string which is in the form to the backend.
My html:
<mat-form-field>
<input matInput [formControl]="date" [matDatepicker]="dp" placeholder="Fill in a date">
<mat-datepicker-toggle matSuffix [for]="dp"></mat-datepicker-toggle>
<mat-datepicker #dp></mat-datepicker>
</mat-form-field>
My ts:
export const MY_FORMATS = {
parse: {
dateInput: 'LL',
},
display: {
dateInput: 'YYYY-MM-DD',
monthYearLabel: 'YYYY',
dateA11yLabel: 'LL',
monthYearA11yLabel: 'YYYY',
},
};
#Component({
selector: 'app-search',
templateUrl: './search.component.html',
styleUrls: ['./search.component.scss'],
providers: [
{provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE]},
{provide: MAT_DATE_FORMATS, useValue: MY_FORMATS, },
],
})
export class SearchComponent implements OnInit {
flightIDInput = new FormControl('WZZ1BW')
date = new FormControl("");
constructor(private dataMessageService: DataMessagesService) { }
ngOnInit() {
}
getMessages() {
console.log(this.date.value);
});
}
}
The value in my form is written as 2019-10-18, but when i call it with this.date or this.date.value it returns this massive object. How can I send the string "2019-10-18" to my backend?

You can format your date value by passing it into the below function in TS...
formatDate(date) {
var d = new Date(date),
month = '' + (d.getMonth() + 1),
day = '' + d.getDate(),
year = d.getFullYear();
if (month.length < 2) month = '0' + month;
if (day.length < 2) day = '0' + day;
return [year, month, day].join('-');}

Related

Vue.js: Child Component mutates state, parent displays property as undefined

I have a parent component that lists all the tasks:
<template>
<div class="tasks-wrapper">
<div class="tasks-header">
<h4>{{ $t('client.taskListingTitle') }}</h4>
<b-button variant="custom" #click="showAddTaskModal">{{ $t('client.addTask') }}</b-button>
</div>
<b-table
striped
hover
:items="tasks"
:fields="fields"
show-empty
:empty-text="$t('common.noResultsFound')">
</b-table>
<AddTaskModal />
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
import AddTaskModal from '#/components/modals/AddTaskModal'
import moment from 'moment'
export default {
name: 'TaskListing',
components: {
AddTaskModal
},
data () {
return {
tasks: [],
fields: [
{ key: 'createdOn', label: this.$t('tasks.tableFields.date'), formatter: 'formatDate' },
{ key: 'domain', label: this.$t('tasks.tableFields.task') },
{ key: 'comment', label: this.$t('tasks.tableFields.comment') },
{ key: 'status', label: this.$t('tasks.tableFields.status') }
]
}
},
computed: {
...mapGetters('users', ['user'])
},
methods: {
...mapActions('tasks', ['fetchTasks']),
...mapActions('users', ['fetchUserById']),
formatDate: function (date) {
return moment.utc(date).local().format('DD.MM.YYYY HH:mm')
},
showAddTaskModal () {
this.$bvModal.show('addTaskModal')
}
},
async mounted () {
const currUserId = this.$router.history.current.params.id
if (this.user || this.user.userId !== currUserId) {
await this.fetchUserById(currUserId)
}
if (this.user.clientNumber !== null) {
const filters = { clientReferenceNumber: { value: this.user.clientNumber } }
this.tasks = await this.fetchTasks({ filters })
}
}
}
</script>
Inside this component there is a child which adds a task modal.
<template>
<b-modal
id="addTaskModal"
:title="$t('modals.addTask.title')"
hide-footer
#show="resetModal"
#hidden="resetModal"
>
<form ref="form" #submit.stop.prevent="handleSubmit">
<b-form-group
:invalid-feedback="$t('modals.requiredFields')">
<b-form-select
id="task-type-select"
:options="taskTypesOptions"
:state="taskTypeState"
v-model="taskType"
required
></b-form-select>
<b-form-textarea
id="add-task-input"
:placeholder="$t('modals.enterComment')"
rows="3"
max-rows="6"
v-model="comment"
:state="commentState"
required />
</b-form-group>
<b-button-group class="float-right">
<b-button variant="danger" #click="$bvModal.hide('addTaskModal')">{{ $t('common.cancel') }}</b-button>
<b-button #click="addTask">{{ $t('modals.addTask.sendMail') }}</b-button>
</b-button-group>
</form>
</b-modal>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
export default {
name: 'AddTaskModal',
data () {
return {
comment: '',
commentState: null,
taskTypesOptions: [
{ value: null, text: this.$t('modals.addTask.taskType') },
{ value: 'OnBoarding', text: 'Onboarding' },
{ value: 'Accounts', text: 'Accounts' },
{ value: 'TopUp', text: 'Topup' },
{ value: 'Overdraft', text: 'Overdraft' },
{ value: 'Aml', text: 'Aml' },
{ value: 'Transfers', text: 'Transfers' },
{ value: 'Consultation', text: 'Consultation' },
{ value: 'TechnicalSupport', text: 'TechnicalSupport' },
{ value: 'UnblockPin', text: 'UnblockPin' },
{ value: 'Other', text: 'Other' }
],
taskType: null,
taskTypeState: null
}
},
computed: {
...mapGetters('users', ['user']),
...mapGetters('tasks', ['tasks'])
},
methods: {
...mapActions('tasks', ['addNewTask', 'fetchTasks']),
...mapActions('users', ['fetchUserById']),
async addTask (bvModalEvt) {
bvModalEvt.preventDefault()
if (!this.checkFormValidity()) { return }
const currUserId = this.$router.history.current.params.id
if (this.user || this.user.userId !== currUserId) {
await this.fetchUserById(currUserId)
}
const data = {
clientPhone: this.user.phoneNumber,
comment: this.comment,
clientReferenceNumber: this.user.clientNumber,
domain: this.taskType
}
await this.addNewTask(data)
if (this.user.clientNumber !== null) {
const filters = { clientReferenceNumber: { value: this.user.clientNumber } }
this.tasks = await this.fetchTasks({ filters })
// this.tasks may be useless here
}
console.log(this.tasks)
this.$nextTick(() => { this.$bvModal.hide('addTaskModal') })
},
checkFormValidity () {
const valid = this.$refs.form.checkValidity()
this.commentState = valid
this.taskTypeState = valid
return valid
},
resetModal () {
this.comment = ''
this.commentState = null
this.taskTypeState = null
}
}
}
</script>
When I add a task I call getalltasks to mutate the store so all the tasks are added. Then I want to render them. They are rendered but the property createdOn on the last task is InvalidDate and when I console log it is undefined.
The reason I need to call gettasks again in the modal is that the response on adding a task does not return the property createdOn. I do not want to set it on the front-end, I want to get it from the database.
I logged the store and all the tasks are added to the store.
Why is my parent component not rendering this particular createdOn property?
If I refresh the page everything is rendering fine.
If you add anything into a list of items that are displayed by v-for, you have to set a unique key. Based on your explanation, I assume that your key is the index and when you add a new item, you mess with the current indexes. Keys must be unique and unmutateable. What you need to do is to create a unique id for each element.
{
id: Math.floor(Math.random() * 10000000)
}
When you create a new task, use the same code to generate a new id, and use id as key. If this doesn't help, share your d-table and related vuex code too.

Vue : How to getting response data into select option (vue-search-select) with axios

im newbie here. I want to display response data from axios on the select option using vue-search-select, I have tried it several times but the results are nil. I have tried looping data using the card and the data is displayed successfully. but here I have trouble displaying data on the select option.
This is my data:
The result is as shown:
This is my select option code:
<model-select :options="hospitals"
option-value="value"
option-text="text"
v-model="item"
placeholder="Choose Hospital">
</model-select>
And this is my script:
import axios from "axios"
import { ModelSelect } from 'vue-search-select'
export default {
data() {
return {
hospitals:[],
item : '',
// options: [
// { value: '1', text: 'aa' + ' - ' + '1' },
// { value: '2', text: 'ab' + ' - ' + '2' },
// { value: '3', text: 'bc' + ' - ' + '3' },
// { value: '4', text: 'cd' + ' - ' + '4' },
// { value: '5', text: 'de' + ' - ' + '5' }
// ],
// item: {
// value: '',
// text: ''
// },
}
},
mounted() {
this.getHospitals();
},
methods: {
getHospitals() {
axios
.get('http://127.0.0.1:8000/my-endpoint')
.then(response => {
this.hospitals = response.data.data
})
.catch(err => {
console.log(err)
})
}
},
components: {
ModelSelect
}
}
Thanks.
use model-list-select instead
so it should be
<model-list-select :list="hospitals"
option-value="id"
option-text="hospital_name"
v-model="item"
placeholder="Choose Hospital">
</model-list-select>
and update your imported component like this
import { ModelListSelect } from 'vue-search-select'
<model-select :options="hospitals"
option-value="id"
option-text="hospital_name"
v-model="item"
placeholder="Choose Hospital">
</model-select>
You have to specify the value key and text key you need in your case.

How to stop input event if my validation failed?

I have simple input and I only need integers, but if I use e.preventDefault() and return to stop input event, input event will be still work.
input
v-on:input="changeFraction"
name="denominator"
type="text"
v-bind:value="fraction.denominator"
data() {
return {
fraction: {
numerator: '',
denominator: '',
},
};
},
methods: {
changeFraction(e) {
const el = e.target;
if (!/[0-9]/g.test(el.value)) {
e.preventDefault();
return null;
}
this.fraction[el.name] = el.value;
},
},
Just use computed for validation and null for #input event when input is not valid.
For instance:
<input type="text" v-model="fraction.numerator" #input="numeratorValid ? changeFraction : null"/>
computed: {
numeratorValid () {
return Number.isInteger(this.fraction.numerator)
}
}
<template>
<div class = "fraction">
<input
#change = "changeFraction"
name = "numerator"
type = "number"
v-model.number = "fraction.numerator"
/>
<input
#change = "changeFraction"
name = "denominator"
type = "number"
v-model.number = "fraction.denominator"
/>
</div>
</template>
<script>
export default {
name: 'FractionItem',
data() {
return {
fraction: {
numerator: '',
denominator: '',
},
};
},
methods: {
changeFraction(e) {
const el = e.target;
//need add plus before value, because writting letter in input change data value to string type
if (!/[0-9]/g.test(+this.fraction[el.name])) {
e.preventDefault();
}
this.$parent.changeFractionInput({
id: this.id,
[el.name]: +this.fraction[el.name],
key: el.name,
});
},
},
};
</script>
<style lang = "scss" scoped></style>

Vue.js - Computed property is not triggered when data is changing

I'm using vue-js and element-ui running on dev-server coming from vue-cli with the webpack template.
I'm trying to debounce the search value of a filterable input. In other words, I would like to debounce the :filter-method and getting the parameters query to do an ajax call
Here is the fiddle example https://jsfiddle.net/ffeohmk4/
In that example there is no debounce yet.
Problem
The function getFinalList is never triggered. I would assume since it is a computed propertyit should be triggered each time this.searchValue changes.
var Main = {
data() {
return {
searchValue : '',
filteredOptions : [],
options: [{
value: 'A',
label: 'A'
}, {
value: 'B',
label: 'B'
}, {
value: 'C',
label: 'C'
}, {
value: 'D',
label: 'D'
}, {
value: 'E',
label: 'E'
}],
value8: ''
}
},
computed : {
getFinalList () {
alert('getFinalList is called');
this.filteredOptions = this.options.filter(option => {
return option.value.toLowerCase().indexOf(this.searchValue.toLowerCase()) > -1;
})
}
},
methods : {
setSearchInput (query) {this.searchValue = query}
},
created () {
this.filteredOptions = this.options;
}
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
Here is a working another example https://jsfiddle.net/ffeohmk4/2/
getFinalList () {
return this.filteredOptions = this.options.filter(option => {
return option.value.toLowerCase().indexOf(this.searchValue.toLowerCase()) > -1;
})
}
<el-select v-model="searchValue" filterable placeholder="Select" :filter-method="setSearchInput">
<el-option v-for="item in getFinalList" :key="item.value" :label="item.label" :value="item.value">
</el-option>

How to bind model list variable to highchart

#model List<Monitoring>
<script>
function drawAWSInstancesMonitoring() {
var seriesData = [];
#foreach (var item in Model)
{
seriesData.push([Date.parse(new Date(parseInt((item.SampleDateTime).substr(6)))), item.PercentUsed]);
}
$('#chart_Monitoring').highcharts('StockChart', {
rangeSelector: {
selected: 1,
inputEnabled: false
},
title: { text: 'Utilization' },
yAxis: { type: 'double', min: 0 },
xAxis: {
type: 'datetime',
labels: {
formatter: function () { return Highcharts.dateFormat('%a %d %b %H:%M', this.value); },
dateTimeLabelFormats: {
minute: '%H:%M',
hour: '%H:%M',
day: '%e. %b',
week: '%e. %b',
month: '%b \'%y',
year: '%Y'
}
}
},
series: [{
name: 'Usage',
data: seriesData,
tooltip: {
valueDecimals: 2
}
}]
});
}
</script>
HTML
<div id="chart_Monitoring" class="col-sm-12" style="height: 350px;"></div>`
how bind directly model to highchart ?
you can not use server variable in js. so you need to parse your model in json like
var model = '#Html.Raw(Json.Encode(Model))';
var data = JSON.parse(model);
var seriesData = [];
for (i = 0; i < data.length; i++) {
seriesData.push([Date.parse(new Date(parseInt((data[i].SampleDateTime).substr(6)))), data[i].PercentUsed]);
}