Storing edited form fields for submittal with Vue - javascript

Objective: I have a form interface that is being loaded with an object's current data for editing. The user opens this modal with the form that is loaded with the current info so they an either edit it or leave it
Currently working: The form loads with the data from my three objects (details, editSubEvents, instructions) and shows properly without issue
My problem: When I edit the fields and hit submit, I'm only currently dumping the submitted data object to make sure I have what I need. I get the eventID fine becasue it won't change and I get it from the original object. However, I need to store the new title, instruction, and subEvents (as an array) in order to submit them because they're obviously different from the origin ones
How can I properly store the new info from these input fields, including storing the new subEvent title and instructions as an array?
<div class="modal-body">
<div class="form-group row" v-for="detail in details">
<p class="modal-title">Title</p>
<input v-model="detail.title" type="text" class="form-control" id="EventTitle" name="EventTitle">
</div>
<div class="form-group row" v-for="subEvent in editSubEvents">
<p class="modal-title">SubEvent Title</p>
<input v-model="subEvent.title" type="text" class="form-control" id="newSubTitle" name="newSubTitle">
<p class="modal-title">SubEvent Instructions</p>
<textarea v-model="subEvent.instructions" type="text" class="form-control" id="newSubInstructions" name="newSubInstructions"></textarea>
</div>
</div>
data() {
return {
details: [],
instructions:[],
editSubEvents:[],
}
},
methods: {
updateEvent() {
let data = {
EventID: this.details[0].event_id,
title:
origin:
instructions:
subEvents: //needs to be an array
};
console.dir(data);
}
}

All of the properties of your data object can be bound to the UI elements (and most of them are, going by your template example code). The properties of the data object are accessible through the Vue component's this.
new Vue({
el: '#vueApp',
data() {
return {
details: [],
instructions:[],
editSubEvents:[],
}
},
methods: {
updateEvent() {
const data = {
EventID: this.details[0].event_id,
title: this.details[0].title,
origin: this.details[0].origin,
instructions: this.instructions,
subEvents: this.subEvents,
};
console.dir(data);
}
}
}

Related

How do i when click button show results in json file with vue?

Yes me again!
This is my project
I want to pull the data from the json file when I fill in the required fields and press the button.
For example, let's write the developer part to the jobs section. then select istanbul as an option and click Find!.
var app = new Vue({
el: "#app",
data: {
founded: [],
search: ""
},
created() {
fetch("job.json")
.then(res => {
return res.json();
})
.then(res => {
this.founded = res.items;
});
},
computed:{
filteredFounded: function(){
return this.founded.filter((items)=> {
return items.positionName.match(this.search)
});
}
}
});
<div class="header">
<h4>Get Job</h4>
</div>
<div id="app" class="nested">
<div class="card w-50">
<div class="search">
<input type="text" class="job" v-model="search" placeholder="Job...">
<select name="" class="city" id="">
<option value="Seçiniz">Seçiniz</option>
<option value="İstanbul">İstanbul</option>
<option value="Ankara">Ankara</option>
<option value="İzmir">İzmir</option>
<option value="Çanakkale">Çanakkale</option>
</select>
</div>
<div class="find">
<button>Find!</button>
</div>
<div class="card-body" v-for="items in filteredFounded">
<h5 class="card-title">{{items.companyName}}</h5>
<p class="card-text">{{items.positionName | to-uppercase}}</p>
<p class="card-text">{{items.cityName}}</p>
<p class="card-text">{{items.townName}}</p>
<p class="card-text">{{items.distance}}</p>
Go!
</div>
</div>
</div>
<script src="script.js"></script>
If I understand your issue:
the view updates on each form change since you bound the card-body repeating div directly to the filtering process, so the "Find!" button isn't used
you don't consider the city selection
To fix these, bind a model to the city selector, and declare separate variables for the JSON data and for the selected data:
<select name="" class="city" id="" v-model="city">
and:
data: {
search: "",
sourceJobs: [],
selectedJobs: [],
city: ""
}
Then put you JSON data in sourceJobs on creation:
fetch("job.json").then(function (res) {
this.sourceJobs = res.json();
});
Side note: this architecture will not be viable for large JSON data, maybe you should consider filtering data through a call to your back-end API... but that's not the current question.
Now that your form data is bound to data.search and data.city, and that your pool of jobs is stored in data.sourceJobs, you want to have a method (no more computed) to filter data.sourceJobs and copy the resulting subset in data.selectedJobs:
methods: {
selectJobs: function () {
this.selectedJobs = this.sourceJobs
.filter((job) => {
return job.cityName === this.city && job.positionName.match(this.search);
})
}
}
Finally, call this method when the "Find!" button is clicked:
<button v-on:click="selectJobs">Find!</button>
In case you change you architecture to go for an API call to do the filtering, then you just need to remove that created part and do the API call from within the selectJobs method.
Side, unrelated note: find/found/found (successful result of searching) vs. found/founded/founded (create, build, set a base for something - a city, a company...).

Vue2 watch Set Not Working

I have a simple Vue app that is supposed to add a number to a Set when you click the "Add to Set" button --
https://codepen.io/jerryji/pen/mKqNvm?editors=1011
<div id="app">
<input type="number" placeholder="enter a number" v-model="n">
<button type="button" #click.prevent="addToSet()">Add to Set</button>
</div>
new Vue({
el: "#app",
data: {
n: null,
nSet: new Set()
},
methods: {
addToSet: function() {
this.nSet.add(this.n);
console.log(this.n + ' added to Set');
}
},
watch: {
nSet: function (newVal, oldVal) {
console.log(newVal);
}
}
});
Why is nothing logged in the console by the watch?
Saving and re Setting the Set using the .values() method on Set worked for me and i didn't have to use $forceUpdate
Using $forceUpdate might be the more sensible way to go though. In some use cases in the past i have found forcing components to update to be problematic.
new Vue({
el: "#app",
data: {
n: null,
nSet: new Set()
},
methods: {
addToSet: function() {
let set = this.nSet;
let newSet = set.add(this.n)
this.nSet = new Set(newSet.values())
}
},
watch: {
nSet: function (newVal, oldVal) {
console.log('newVal', ...newVal);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="app">
<input type="number" placeholder="enter a number" v-model="n">
<button type="button" #click.prevent="addToSet()">Add to Set</button>
<p>n = {{ n }}</p>
</div>
Vue adds special handling for Arrays, but not for Sets. As a result, Vue doesn't automatically detect changes to Set membership. You can force an update, though
this.nSet.add(this.n);
this.$forceUpdate();
It's because Vue doesn't support Set, Map, WeakSet and WeakMap. And it's because browsers didn't support these structures well. Especially WeakMap. But... They decided to support these structures. Maybe in version 3 - when they decide to drop support for older browsers. So, for now use an object, add properties with Vue.$set() and watch for changes with deep: true.

Search Filtering with Vue2

<!-- Facets in the v-for below is an array of objects, each element (facet) in the
facets array has a property which is an array of facetItems. -->
<div class="row" v-for="(facet, facetsIndex) in facets" :key="facetsIndex">
<!-- Since we are inside the v-for, it creates a search input for each facet.
Each facet search input will only search for facetItems belonging to that facet.
We know which facet to search in because we pass the facetIndex to the searchFilter function. -->
<input type="text" #keyup="searchFilter(facetsIndex)">
<div v-if="facet.facetItems.length > 0">
<div class="facet-header">{{config[core.toLowerCase()].displayNames[facet.facetName]}}</div>
<div class="row facet-scroll" >
<!-- The v-for below is used to iterate over the facetItems for each facet. displayFacetItems() is called
for each array of facetItems corresponding to each facet on initial render. displayFacetItems() is also called
on each keyup event emitting from the corresponding facet search input. displayFacetItems() should return an
array of facetItems objects, and when a search input is entered, it should return a filtererd array of facetItems
based on the search results. -->
<div class="facet-item" v-for="(item, facetItemIndex) in displayFacetItems(facetsIndex)" :key="facetItemIndex">
<facet v-bind:item="item" v-bind:facet="facet"></facet>
</div>
</div>
<hr class="divider"/>
</div>
</div>
methods: {
searchFilter (facetsIndex) {
let searchTerm = event.currentTarget.value
this.displayFacetItems(facetsIndex, searchTerm)
},
displayFacetItems (facetsIndex, searchTerm) {
if (!searchTerm) return this.facets[facetsIndex].facetItems
return this.facets[facetsIndex].facetItems.filter((facetItem) => {
return _.includes(facetItem.name.toLowerCase(), searchTerm.toLowerCase())
})
}
},
Please see the comments in the code above for an explanation of what's happening in my code.
I don't understand why my code above isn't working. I'm trying to implement search functionality for each facet. When searching, the filtering should only happen for facetItems belonging to that specific facet.
I've been able to verify that displayFacetItems does return an array of filtered facetItems but for some reason the filtered array isn't updated in the DOM.
This might have something to do with Vue's data binding or the process in which Vue updates the DOM. Any pointers on what I'm doing wrong is greatly appreciated.
My code took inspiration from this article:
https://nickescobedo.com/1018/introduction-to-vue-js-filtering-with-lodash
You can see my jsfiddle for search items on Vuejs. I hope this will help you.
<div id="app">
<label>
Search name: <input type="text" v-model='searchString'>
</label> <br>
<transition-group tag='ul' name='my-list'>
<li v-for='item in filteredList' :key='item.id' class="my-list-item">
{{item.name}}
</li>
</transition-group>
</div>
<script>
const app = new Vue({
el: '#app',
beforeMount() {
const req = fetch('https://jsonplaceholder.typicode.com/users');
req.then(response => {
if (response.ok) {
return response.json();
}
throw new Error('Bad request: ' + response.status);
})
.then(users => {
this.users = users;
this.nextId = this.users.length + 1;
});
},
data: {
searchString: '',
users: [
{id: 1, name: 'Alex'},
{id: 2, name: 'Bob'},
{id: 3, name: 'Sandy'},
],
},
computed: {
filteredList: function() {
const searchString = this.searchString.toLowerCase();
return this.users.filter(item => item.name.toLowerCase().includes(searchString));
}
}
});
</script>
The param facetsIndex is not reactive, please take a look at your jsconsole, you should have a warning about this and not only this, your code logic is totally wrong.
You could use a v-model on input,
create a filteredFacets property,
use this property in your loop.
Just an example, you should read more about how VueJS works :
https://v2.vuejs.org/v2/guide/

emberjs using AND on querying from mongodb

I'm working on an Emberjs application and I've got quite far with it
but i'm having an issue and I think that I've looked at every corner in the
web without finding the solution
Now my problem is that I have a dropdown that queries record on change "meaning" I have a "Dental" Department which contains "Braces" as a service
(service belongs to department) so when the user changes the dropdown option a query runs to filter the results again but within the results showing there is a text field which should be able to allow the user to search within the services shown accordingly to the selected department.
So far so good. The problem is that when the user starts typing to filter the data the condition in which services belongs to the selected department won't work any more so is there a way to use AND in my "Ember" controller to query records with more than one condition ?
Here is my Template
<div class="form-group">
{{#power-select
options=departments
selected=selectedDepartment
searchField="name"
placeholder="Select Department..."
onchange=(action (mut selectedDepartment))
dropdownClass="in-modal-dropdown"
renderInPlace=true
as |department|
}}
{{department.name}}
{{/power-select}}
</div>
{{#if selectedDepartment}}
<hr />
<div class="form-group has-feedback">
{{input value=searchText class="form-control input-sm" placeholder="Search Services" insert-newline="doSearch"}}
{{#if searchText}}
<i class="glyphicon glyphicon-remove form-control-feedback"></i>
{{/if}}
</div>
<br />
{{#each departmentServices as |service|}}
<button {{action 'selectService' service}} class="ux-product-override-for-request w-clearfix w-inline-block">
<div class="ux-product-icon"></div>
<div class="ux-product-title">{{service.name}}</div>
<div class="ux-product-price">{{service.price}} RS</div>
</button>
{{/each}}
{{/if}}
and my Controller
store: Ember.inject.service(),
departments: Ember.computed(function(){
return this.get('store').findAll('department')
}),
departmentServices: Ember.computed('selectedDepartment', 'search', function(){
if(this.get('search') == '' || this.get('search') == null){
console.log(this.get('search'));
return this.get('store').query('service', {
where: {
department: this.get('selectedDepartment.id')
}
})
} else {
return this.get('store').query('service', {
where: {
{ department: { this.get('selectedDepartment.id')} }
{ name: { contains: this.get('search')} }
}
})
}
}),
selectedDepartment: null,
{{input value=searchText - here you are using searchText but in departmentServices computed property you are using search but this is not the actual issue.
Issue is, this.get('store').query will return the Promise not the value so your implementation will not work out.(if you want to make it work you can try 3rd options Special promise-backed objects mentioned https://emberigniter.com/guide-promises-computed-properties/)
I will encourage you to introduce setDepartmentServices function which will query and update departmentServices property. and power-select for onchange instead of using the mut you can use onchange = (action 'setSelectedDepartment') and searchText input filed doSearch will call setDepartmentServices.
Here is the pseudo code,
setDepartmentServices() {
//this will do query and will set the result in departmentServices property.
}
actions: {
setSelectedDepartment(selectedDepartment) {
this.set('selectedDepartment', selectedDepartment);
//check if its ok to update departmentServices
this.send('setDepartmentServices');
}
doSearch() {
//check if its ok to update departmentServices
this.send('setDepartmentServices');
}
}

How to get an input field value in Vue

I'm new to Vue and I would like some help getting a value from an input field:
In my form I have:
<input type="hidden" id="groupId" value="1">
If I was using jQuery I would do:
var group_id = $('#groupId').val();
However, in Vue I don't know how to bind the hidden field:
<div id="app">
<input type="text" v-model="groupId"> //Where do I put the value?
</div>
new Vue({
el: '#app',
data: {
groupId: //What do I put here to get the field's value?
}
How can I achieve this?
Update to the update: See this answer. Previously updated answer was wrong.
Original answer:
In Vue, you don't get things from the view and put things into the view. Vue does that. You do all manipulations in the viewmodel, and make bindings in the view so that Vue knows how to synchronize it. So you'd bind the input to your model data item:
<input type="hidden" id="groupId" v-model="groupId">
and set its value in your viewmodel:
data: {
groupId: 1
}
I had the same question. I'm working with Vue + Laravel.
For me, the solution was simple after searching and not finding a concrete solution in the Vue documentation.
Simply:
document.getElementById('MyId').value;
Details in → https://www.w3schools.com/jsref/prop_text_value.asp
It is not the most efficient solution, but it works for now!
Greetings.
Working sample of getting value from input field in this case it is hidden type:
<input type="hidden" name="test">
<script>
new Vue ({
created () {
const field = document.querySelector("input[name=test]").value
console.log(field)
}
})
</script>
this code helped me
i hope that this work with you
define the input
<div class="root">
<input type="hidden" ref="groupId" value="1">
<button type="button" v-on:click="get_id()">test</button>
</div>
define the method
new Vue({
el: ".root",
data: {
id: null,
}
methods: {
get_id() {
this.id = this.$refs.groupId.value;
}
}
});
// if you want it displayed on your page, use {{ groupId }}
/* you can get the value by using #change.enter=".." #keypress.enter="getInputValue",
or #input="getInputValue" or #click="getInputValue" using button,
or if it is with a form element, #submit.prevent="getInputValue" */
/* #keypress.enter tracks input but only calls the function when the Enter key
is pressed, #input track changes as it's being entered */
// it is important to use event.preventDefault() when using #change or #keypress
<div id="app">
<input type="text" v-model="groupId">
<p> {{ groupId }} </p>
<button #click="getInputValue">Get Input</button>
</div>
new Vue({
el: '#app',
data: {
groupId: //What do I put here to get the field's value?
// for what to put there, you can use an empty string or null
groupId: "",
},
// to get the value from input field
methods: {
getInputValue: function() {
if(this.groupId !== "") {
console.log(this.groupId);
}
},
}
})
look at this I did it in laravel, vuejs, vuetable2 and children's row, and don't use the v-model:
this.$refs['est_'+id_det].localValue
en VUE:
<div class="col-md-3">
<b-form-select class="form-control selectpicker" :ref="'est_'+props.row.id_detalle_oc"
:value="props.row.id_est_ven" v-on:change="save_estado(props.row.id_detalle_oc)">
<option value="0">Sin estado</option>
<option value="1">Pendiente</option>
<option value="2">Impresa</option>
<option value="3">Lista</option>
</b-form-select>
in methods
methods: {
save_estado:function (id_det){
var url= 'ordenes-compra/guardar_est_ven'
var id_estado = this.$refs['est_'+id_det].localValue
axios.post(url,{
id_det: id_det,
id_est_ven: id_estado,
est_ven: est_ve
}).then(function (response) {
var respuesta= response.data;
if(respuesta == "OK"){
swal({
type: 'success',
title: '¡Éxito!',
text: 'Estado modificado',
confirmButtonText: 'Entendido',
})
}
})
.catch(function (error) {
console.log(error);
});
},
I hope it helps, I've been hanging around for a while.
Regards
Hi you can also try the following:
const input = this.$el.firstElementChild;
in case you are using TypeScript, declare input as:
: HTMLInputElement
Then, you can simply get the value if you do:
input.value
Hope it helps!
Ok, this does the job: document.querySelector('#groupId').getAttribute('value');

Categories