I am having trouble with a computed property within dynamically populated array of objects.
I have an array of customers which are filled dynamically by the user in the form. The user can add as many customers as he likes.
Each customer has a price field calculated based on some other values in the object. Additionally, the price for each customer is based on some generic settings that apply to all customers.
Therefore I have a computed function which should update the price for each customer. The function starts like this:
this.booking.customers.forEach(function(customer) {
var price = 0;
self.booking.packages.forEach(function(package) {
... // based on the packages the price variable is changing
}
customer.price = price;
}
The calculation works - because if I open the vue devtools the value is suddenly applied, and then Vue also recognizes the dependencies (as soon as I change some value all prices adapt accordingly).
So my problem is: initially, Vue doesn't update the property correctly. As soon as I open devtools once, from that moment on it adapts accordingly.
Maybe I am not using computed properties in the right way, but using a method is also not what I need because I want the price value to change as soon as any dependency is changing.
Hope the problem is understandable. Thanks in advance for your help.
EDIT:
Here is a fiddle which maybe highlights the problem better. I think I am misusing computed values, but I have no idea how to tell Vue that the prices need to change whenenver some other values change.
http://jsfiddle.net/6bw50j9d/2/
ANOTHER EDIT:
I was able to solve my problem using deep watchers, I found this solution in another post. See Vue.js - How to properly watch for nested properties
Related
I'm very new to Vue and looking for some help. I would like to perform a calculation where a number of a particular class name (showClosed) can be subtracted from the results count. Is this even possible?
I get how many records are returned using this code below
resultCount() {
return Object.keys(this.results).length;
},
This returns all records including the ones which are 'hidden' using CSS.
The problem I have is I want the 'count' to change depending on whether the expired items are displayed or not. The hidden items all have a class of 'hidden' so I wondered if I could subtract the items with the class hidden from the overall count. I'm sure there is a better way, I just don't know what it is. Any help is appreciated.
I'd do it like this, assuming that items that have a deletedAt that is not null or undefined are supposed to be hidden. It's generally easier to work from a data perspective, rather than setting the CSS class first and then trying to get data information from which CSS class is set again:
computed: {
visibleResultsCount() {
const hiddenItems = this.result.filter(x => x.deletedAt != undefined) // this callback function is assumed for my case, and should be the same as the one you use to check if you should hide with CSS.
return Object.keys(this.result).length - Object.keys(hiddenItems).length;
}
Of course you could also filter on visible items instead and get the length from that. The main takeaway is to compute with the data itself rather than trying to count elements with a CSS class.
I'm trying to add objects (simple key-value pairs) to a list.
However, the v-model is still bound to the previously added objects, so if I add "ObjectOne" vith "ValueOne", then try to add "ObjectTwo" with "ValueTwo", "ObjectOne" gets edited AND "ObjectTwo" gets added.
I am by no mean an expert in Javascript, so it might not be related to VueJS.
I can obviously make this work with a method per list .
The point is that my model has multiple lists of key value pair to be edited, so I tried making a generic method :
addToList: function(value, list){
console.log("Adding " + value + " to list "+list);
list.push(value);
value={};
},
This method works if used on "simple" lists (like an array of string), but not on "objects" list.
My guess is that as I try to clean "value" instead of "this.value", the reference still points to the same object, but since I don't know what "value" will be when called, I don't know how to do this.
Here is the fiddle with a re-creation of my issue.
My objective would be to be able to use the "addToList" function to add to any list, without having to re-write a function for each list.
Thank you for your help.
The above behaviour is because you are updating the value of same object whenever you add a new todo task.You need to set your object again to add new values as below.
addToList(value, todos){
this.todos.push(value);
this.anotherTodo={ text:'',
done:'false'}
}
Working fiddle here.
I post this as an answer, but if someone has a better way to do it, I'm all hear.
I solved the way by adding a watch on my list. When the list changes, I clean the model object that's added to it.
In my production work, I had to add a computed property, since I can't add a watch on an object's property, then a watch on said computed property :
watch:{
todos(){
this.anotherTodo={};
},
fiddle as demo
I am currently generating a table which lists problems encountered during the selected test using a component generated with this code:
<tr is="entry" v-for="problem in problems" :key="problem.id" v-bind:foo="problem"></tr>
Each problem corresponds to an item whose relevant information is contained within the problem dictionary and referenced in the first few columns of the table. Since the same item can have multiple problems, the same item can appear in multiple rows of the table. Now, each row features some buttons which allow you to modify the underlying item so as to fix the problems.
Whenever I modify one of those underlying items I need to modify it in all the rows, which i do by calling a function in the parent component, but modifying the data inside of the dictionary does not seem to trigger any of my watches or computes inside of the child component, which currently looks something like this:
Vue.component('entry', {
props: ['foo'],
data: function(){
//does some computations
return data
},
watch:{
foo: function(){
this.recompute_entry()
},
},
methods:{
//various methods, including:
recompute_entry: function(){
//updates the data according to changes brought to the entry
},
},
});
I have attempted to include a different prop which i could bind to an entry in a list in my parent component but, besides being pretty clunky, that didn't end up working either, which makes me think I might've gotten something wrong with my component.
Ultimately, I have relied on the fact that v-for iterates through my list in an orderly fashion, which combined with the fact that I generate no other children in my parent component means that a child component would have the same index in my component's children array as it would in my problems array. Therefore I can use this:
this.$children[problem_index].recompute_entry();
Which kind of feels hack-ish and unreliable, but actually works, for once. Is there no alternative safer method to recalculate my child components based on changes made to their props? I really feel there has to be.
I probably would need to see the exact implementation but it sounds like you need to clone your dictionary to trigger the prop change, ie:
let newProblem = Object.assign({}, this.problem);
// change any nested property
newProblem.some.value = 1
// assign back the cloned and modified dictionary
this.problem = newProblem
I'm calling:
- (void)updateWithValues:(NSDictionary *)values
version:(uint64_t)version
in an NSIncrementalStore subclass in order to update the cache with update NSManagedObject values. My question concerns the values argument. Do I only need to put in the updated attributes or a complete new copy of the data?
The description in the documentation says: "Update the values and version to reflect new data being saved to or loaded from the external store. // The values dictionary is in the same format as the initializer."
It isn't clear to me whether or not the "values" that "reflect the new data" refers to only the updated attributes or all the attributes in the object.
It requires the complete data. I agree it wasn't very clear but I suppose the reason is so you can do the conflict handling first. The annoying thing is there is no way to get the values back from the node to merge in the new ones and set them again. Annoyingly this means you can't use the node as your cache object, I'm still learning the NSIncrementalStore so likely there reason for this design will come clear at some point.
How can we check whether the given object is a list or other type
in velocity. In that list i have another list which i need to iterate again.
I also have another data in the parent list which i want to print while iterating parent list. But the problem is the child list object also get printing with actual data. So i want to print the data by checking whether its list or not. Any help is much appreciated.
Before you get any remarks on using too much logic in templates, try this reflection based approach :
velocity (test instanceof)