dynamic change doesn't work on vuejs input - vue.js

i'm working on a vue file and have a form :
<div class="input-group">
<span class="input-group-addon">Montant</span>
<input type="number" class="form-control" v-model="amount" v-bind:value="pattern['value']"]>
</div>
my tab pattern is loaded like that :
var request = $.ajax({
url: '{{ path ('home') }}promos/pattern/'+value,
})
request.success(function(data){
if(data['pattern']==='yes'){
this.pattern=data[0];
alert(this.pattern['value']);
}
})
and my instance :
var instance = new Vue({
el: "#General",
data: {
[...]
pattern: []
}
and the request is made evertyime i do 'action a'. I have the right alert with the value i want everytime i do 'action a' but the input stays at 0 and won't dynamically change.

Something is wrong with your code. Firstly, let's look at your ajax request:
request.success(function(data){
if(data['pattern']==='yes'){
this.pattern=data[0];
alert(this.pattern['value']);
}
})
What is the form of your data response? Because you are checking something with data['pattern'], and then you are trying to associate to this.pattern something that you call data[0]
Then, as stated in #thanksd answer, you are referencing a wrong this in your ajax callback, you need to create a self variable:
var self = this
var request = $.ajax({
url: '{{ path ('home') }}promos/pattern/'+value,
})
request.success(function(data){
if(data['pattern']==='yes'){
self.pattern=data[0];
alert(this.pattern['value']);
}
})
Finally, you write:
<input type="number" class="form-control" v-model="amount" v-bind:value="pattern['value']"]>
So there are a few mistakes here. Firstly, you have a ] at the end of the line that has nothing to do here.
Secondly, you are using v-bind:value, this is not something that is going to be responsive. If you want this input to be responsive, you should use v-model and set the value of amount when you want to change the input value.
Hope this helps

Three things:
The this in your success handler is not referencing the Vue instance. You need to set a reference outside the scope of the handler and use that instead.
You can't chain a success callback to jQuery's ajax method in the first place. It's defined as a property in the parameter object passed to the call. (Maybe you copied code over wrong?)
You need to get rid of v-model="amount" if you want the input's value to reflect the value bound by v-bind:value="pattern"
Your code should look like this:
let self = this; // set a reference to the Vue instance outside the callback scope
var request = $.ajax({
url: '{{ path ('home') }}promos/pattern/'+value,
success: function(data) { // success handler should go in the parameter object
if (data['pattern']==='yes') {
self.pattern=data[0];
alert(this.pattern['value']);
}
}
})

Related

Vue.js: binding select boxes, but don't want to ajax all the options

Good day. I'm using Vue.js to render an arbitrary number of select elements from the data in a component.
Here's sample JSON data that indicates there are two select elements, each with one or more options.
{
"dropdowns":[
{
"cd":"UG9ydGZvbGlv",
"formname":"sp_filter_UG9ydGZvbGlv",
"nm":"Portfolio",
"selected":"1a",
"options":[
{
"cd":"1a",
"val":"Option 1A"
}
]
},
{
"cd":"UHJvZHVjdCBOYW1l",
"formname":"sp_filter_UHJvZHVjdCBOYW1l",
"nm":"Product Name",
"selected":"2b",
"options":[
{
"cd":"2a",
"val":"Option 2A"
},
{
"cd":"2b",
"val":"Option 2B"
}
]
}
]
}
Here's the template HTML:
<form>
<div v-for="dropdown in dropdowns">
<div v-if="dropdown.availableToView">
<h4>{{dropdown.nm}}</h4>
<select v-model="dropdown.selected" v-on:change="triggerUpdate">
<option value="">(Make a selection)</option>
<option v-for="option in dropdown.options" :value="option.cd">{{option.val}}</option>
</select>
</div>
</div>
</form>
So far so good.
I've got the data loading and Vue is building the dropdowns.
When the user changes any select box (remember there can be an arbitrary number of them), the trigger action needs to submit ALL of the elements in the form via ajax. It sounds like the most correct option is to bind the form fields to the underlying component data, as I've done.
My triggerUpdate looks like this:
methods: {
triggerUpdate: function() {
axios({
method: "post",
url: actionURL,
data: this.dropdowns
})
.then(response => (this.data = response));
}
}
...but this submits the entire dropdowns data element, including all of the options in each select box. It's unnecessary to send all of the options in. I just want to send each field name along with its selected option (i.e. the "value").
I know i could serialize the whole form and make that my ajax payload. But that seems to be making an "end run" around Vue.js. Everyone talks about having your form fields bound to the Vue model...is it then correct to basically ignore the model when making an ajax request whose purpose is to then update the model?
I'm relatively new to Vue.js so I'd appreciate help with what I'm overlooking here. How should I go about sending in the data from the form (a) while using proper Vue.js binding and (b) without sending extraneous data?
Thanks for your time.
If you need to post only the selected values, and you store those in each dropdown's selected property, the sensible approach seems to be just mapping it to a simple array of name/value objects.
Try this (it assumes the name of each field is the formname property, if it isn't you can just replace it):
var submitData = this.dropdowns.map((dropdown) => {
return { name: dropdown.formname, value: dropdown.selected };
});
Then you send submitData in your ajax request.

set value of input programatically doesn't refresh component DOM

I have an input which is bidden to property message. I have a set button , which I use for changing of input value programmatically. When the button is pressed, value of input is correctly changed to 'xxxx'. when I press clean button after that , the input is correctly cleaned but when I repeat pressing set and clean again the input does not get cleared anymore.
Working example is here:
https://codepen.io/dan-ouek/pen/rNBjxRO
<div class="container">
<div id='root' class="box">
<input ref="templateFilter" type='text' id='input' v-model='message'>
{{ message }}
<button #click="set">set</button>
<button #click="clean">clean</button>
</div>
</div>
new Vue({
el: '#root',
data: {
message: 'Hello Vue'
},
methods: {
set: function () {
let element = this.$refs.templateFilter
Vue.set(element, 'value', 'xxxx')
}, clean: function () {
this.message = ""
}
}})
Questions:
1) Is it possible to change input programmatically without working with bidden property value? Something like direct DOM manipulation:
let element = document.getElementsByClassName("templateFilter")[0]
element.value = 'xxxxx'
but with proper component refresh?
2) Why is the {{ message }} not refreshed after calling set method?
Why is the message not refreshed after calling set method?
When you type something on your input the message data gets updated via an event handler BUT when you set it programmatically the event handler is NOT triggered and that's why message was not getting updated / refreshed....
Solution :
a short solution to your issue would be just to mutate the message value this.message = "xxxx" but if you insist on making that programmatically you have to trigger the input event :
set: function() {
let element = this.$refs.templateFilter
Vue.set(element, 'value', 'xxxx')
element.dispatchEvent(new Event('input'))
}
Here is a Demo : codepen

V-select bug while selecting elements in Vuejs

I'm building a small application in vuejs 2 where I'm using v-select package for select box, Problem I'm facing is:
I've declared v-select in my component something like this:
<div class="form-group"><label class="col-sm-2 control-label">Company name:</label>
<div class="col-sm-6">
<v-select :options="companyOptions" v-model="company_name" :on-search="getOptions" placeholder="Company name"></v-select>
</div>
</div>
So accordingly I'm having data defined as company_name, and I'm calling an axios event to get the searchable data, while the component is being loaded I'm calling index data of first 50 set for initial selection and if anybody types then I'm calling a function getOptions to get data related to the input, now suppose if somebody selects any data and then removes it again from the selection and again search with key press event the searchable data is not displayed, I can see that my axios call is working fine and I'm able to get the relevant data. but it is not displaying in dropdown as it says:
Error in render function: "TypeError: Cannot read property 'label' of null"
Which is coming from the company_name model which was selected. Following is my code in codepen
In this my axios is not working as it says mixed content:
https://codepen.io/anon/pen/Bdeqam?editors=1011' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://connect.stellar-ir.com/api/companies'. This request has been blocked; the content must be served over HTTPS.
So I'm unable to explain properly in this code set. But my code looks same as declared in codepen.
Help me out in this.
The error is because your computed values are undefined and undefined is not a string, so no string methods (toLowerCase()) are available. The response.data.model.data must look like this:
[
{
id: 1234,
name: 'example'
}, {
id: 12345,
name: 'example2'
}
]
if you get an object instead of an array push it to the array: this.serverData.push(response.data.model.data)
Replace your axios call with:
this.serverData = [
{
id: 1234,
name: 'example'
}, {
id: 12345,
name: 'example2'
}
]
to test it.
In your getOptions() method you calling loading(true or false), but your fetchIndexData() method has an asynchronous axios call. Use async/await, a callback function or a promise chain to wait for the data and show the loading indicator correctly.
On every keypress an request is send to the server i would recommend to use a debounce function.
Tipp
Line 42: https://stackoverflow.com/a/42028776/6429774
axios.post('http://connect.stellar-ir.com/api/companies', searchData).then(response => {
if(response.status === 200)
{
this.serverData = response.data.model.data
}
}).catch(error => {
console.log(error)
});

vue.js method can't access variable from data object with multiple rows

I am currently learning vue.js and having trouble accessing data in the methods.
data is loaded and set as a global variable (for now, this will probably change but not part of the problem now i think)
through ajax call this data is received:
data":[{"itemId":"58646f066803fa62388b4573","color":"#ffb878","name":"test1","startDate":"04/24/2017","work":"9.25"},{"itemId":"58646f066803fa62388b4572","color":"#ffb878","name":"test2","startDate":"04/24/2017","work":"4.25"},{"itemId":"58646f066803fa62388b4571","color":"#a4bdfc","name":"test3","startDate":"05/01/2017","work":"24.00"}]
which is set as a global (variable data is set outside of the functions) with:
...success: function (jsonObj)
{
data['item'] = jsonObj.data
....
now for the vue part:
var app = new Vue({
el:'#canvas',
data: {
items: data['item']
},
methods: {
moveItem: function(){
console.log("new date: "+this.startDate);
}
}
})
the html:
<div v-for="row in items" class="entirerow" v-bind:id="'row'+row.itemId">
<div class="itemrow">{{ row.name }}</div>
<div class="itemrow"><input type="text" v-model="row.startDate" #change="moveItem"></div>
<div class="itemrowlast">{{ row.work }}</div>
</div>
this nicely shows 3 rows with the correct data in each row. So far so good. But now if I change something in the input value the method moveItem is triggered but states "new date: undefined" in the console.log
I've tried console.log("new date: "+this.items.startDate) as well but no cigar and then it would seem the method wouldn't know which row is handled.
How can I access the correct data in the method, so from a certain row in the loop?
Thanks!
You refer to data object in method (this.startDate) not to item
moveItem: function(){
console.log("new date: "+this.startDate);
}
You can change your code like this
template
#change="moveItem(row)"
script
moveItem: function(row){
console.log("new date: " + row.startDate);
}

access object with dynamic variable vue.js

This is my object
var users ={
twitter : {
name : //,
lastname : //
},
facebook : {
name : //,
lastname : //
}
}
}
I have a dynamic variable activeuser that updates from Facebook to twitter.
What i'm trying to do is refer to the inner object in users depending on the value of activeuser. I need to give my div something like this class :
<div class=' {{users.activeuser}}'></div>
I know this is not how it should be done with vue.js. Do you have any suggestions?
Thank You!
Using VueJS you should be able to assign your dynamic variable to a Vue Model when you load the new object using a Vue setter $set('property name', 'value')
Example AJAX retreival:
$.getJSON('myURL.html?query=xxx', function(data, textStatus, jqXHR){
try{
MyVue.$set('dynamicObject', data);
}
catch(e){}
});
A generic Vue may look like this:
var MyVue = new Vue({
el:'#exampleDiv',
data: {
dynamicObject : ''
}
});
Bound to an example HTML element:
<div id="exampleDiv">
<label class="{{dynamicObject.activeuser}}">{{dynamicObject.username}}</label>
</div>
In the case that you have an object with an array of objects which also contain properties Vue makes it very simple to create many HTML elements (for each child object) by simply adding a v-repeat (example) to the desired HTML and assigning the datasource:
<div id="exampleDiv">
<label v-repeat="dynamicObject" class="{{dynamicObject.activeuser}}"></label>
</div>