Vue v-for showing wierd behaviour upon updating the array - javascript

My project currently has a list of Comments stored in an array called feedbackList.
Let's say that each comment contains a Author and Feedback string.
So, my feedbackList would be something like;
feedbackList: [
{name: 'John', comment: 'a nice comment'},
{name: 'Steve', comment: 'first comment'}
]
These are then displayed using some code such as;
<div class="comment-wrapper" v-for="(comment, index) in feedbackList" :key="index">
<CommentCard
v-bind:author="comment.author"
v-bind:comment="comment.comment"
v-on:DeleteComment="DeleteComment($event)"
/>
</div>
Then, I use a function to submit a new comment, containing this;
const newcomment = {
author: this.author
comment: this.feedback,
timePosted: moment().format()
}
this.feedbackList.unshift(newcomment)
However, the issue is as I push the new comment to the beggining of the array, my comments shuffle down in an odd way.
I will now appear as the person below me (author), but with my own comment.
The post below that will take on the one before that, with the previous author but their own comment, and so on and so on.
If I use .push(newcomment) it adds the new comment to the bottom as intended. However, then comes the issue of deleting a comment, making the previous one now take over the recently delete author, but their own comment.
I know this is a little confusing, but essentially upon updating my array, it seems the v-for is not updating the attached data correctly and giving the correct comment but previous author.

That's because your index is binded as a key. Try adding an id variable (unique for every comment, it can be an incrementing number or a random string) and use that as your key in v-for.
Example:
feedbackList: [
{id: 'nlgvn5d6', name: 'John', comment: 'a nice comment'},
{id: '85m18efd', name: 'Steve', comment: 'first comment'}
]
Remeber that when adding a new item to the list it also needs to have its own unique id.
Then you can use it like this:
v-for="comment in feedbackList" :key="comment.id"

Related

JavaScript Objects using this keyword

I'm currently working on some practice for JavaScript and am really confused about what I am to do here. Any help would be appreciated!
Define a method named orderOfAppearance() that takes the name of a role as an argument and returns that role's order of appearance. If the role is not found, the method returns 0. Ex: orderOfAppearance("Elizabeth Swann") returns 3. Hint: A method may access the object's properties using the keyword this. Ex: this.title accesses the object's title property.
// Code will be tested with different roles and movies
let movie = {
title: "Pirates of the Caribbean: At World's End",
director: "Gore Verbinski",
composer: "Hans Zimmer",
roles: [ // Roles are stored in order of appearance
"Jack Sparrow",
"Will Turner",
"Elizabeth Swann",
"Hector Barbossa"
],
orderOfAppearance: function(role) {
/* Your solution goes here */
if (!(role in this.roles)) {
return 0;
}
return this.role;
/*Solution ends here */
}
};
A doubly linked list has 2 links. Let's use common sense for a moment instead of blind deferral to whatever you think your TA said: "Doubly linked list" obviously implies "2 links", otherwise that'd be an extremely silly name, no?
So, there must be 2 links. You seem to be under the impression that 'you must not have a pointer to the tail' implies 'there must be only one link'. That can't be right, what with 'doubly linked list' and all.
The right answer is presumably that each node has 2 links, but these links aren't 'head and tail', but 'next' and 'previous'.
For a ringed list (where moving forward from the last element gets you back to the first, and moving backwards from the first element gets you to the last), the last node's "next" link goes back to the first node, and conversely, the first node's "previous" link goes to the last (so it points at the same thing a hypothetical 'tail' would point to).
However, that'd be only true for the first node in your linked list structure (that would be the only node for which 'prev' points at the tail).
Your TA either means 'have next/prev links, not next/tail links' as per above, or has no idea what they are talking about. Let's give em the benefit of the doubt ;) – as it's homework I'll leave the actual writing of the data structure, using a definition of DoublyLinkedNode<T> that includes fields DoublyLinkedNode<T> next, prev;, as an exercise for you.
What I was looking for was to refer to the last use first.getPrev(), since its a circle the last is before the first.
I have the same question. This is found in a zybooks online textbook. The textbook's portion of JavaScript is horrible!! It explains little about what we need to do to solve the questions posed. I have been so frustrated and had to look to online sources to try to solve the problems in the book. Was there a solution to this question?
Define a method named orderOfAppearance() that takes the name of a role as an argument and returns that role's order of appearance. If the role is not found, the method returns 0. Ex: orderOfAppearance("Elizabeth Swann") returns 3. Hint: A method may access the object's properties using the keyword this. Ex: this.title accesses the object's title property.
// Code will be tested with different roles and movies
let movie = {
title: "Pirates of the Caribbean: At World's End",
director: "Gore Verbinski",
composer: "Hans Zimmer",
roles: [ // Roles are stored in order of appearance
"Jack Sparrow",
"Will Turner",
"Elizabeth Swann",
"Hector Barbossa"
],
orderOfAppearance: function(role) {
\\your solution goes here
return this.roles;
}
};
I entered return this.roles; but everything else in the code came from the computer. the answer comes up wrong and says:
Testing orderOfAppearance("Elizabeth Swann")
Yours and expected differ. See highlights below.
Yours
Jack Sparrow,Will Turner,Elizabeth Swann,Hector Barbossa
Expected
3
I also entered:
return this.roles[3]
but that gives Hector Barbossa. I don't know what to do!
If the role is not found, the method returns 0. Ex: orderOfAppearance("Elizabeth Swann") returns 3.
You can use .indexOf() to get the index of the role passed to the orderOfAppearance() method and then add 1 to it. .indexOf() will return -1 if the role is not found and it will become 0 after adding 1.
let movie = {
title: "Pirates of the Caribbean: At World's End",
director: 'Gore Verbinski',
composer: 'Hans Zimmer',
roles: ['Jack Sparrow', 'Will Turner', 'Elizabeth Swann', 'Hector Barbossa'],
orderOfAppearance: function(role) {
return this.roles.indexOf(role) + 1
},
}
console.log(movie.orderOfAppearance('Jack Sparrow'))
console.log(movie.orderOfAppearance('Will Turner'))
console.log(movie.orderOfAppearance('Elizabeth Swann'))
console.log(movie.orderOfAppearance('Hector Barbossa'))
console.log(movie.orderOfAppearance('Something that does not exist in roles'))

Can someone explain Angular as-for-in expression notation?

In Angular loops (ng-repeat, ng-options) you can use the following syntax:
item as item.label for item in items
Can someone please explain what each of the tokens in the expression is doing there and what it means? Can you point me to the documentation of this? I can't figure out what to search for (searching for 'as' or 'for' is useless). It is not mentioned in the documentation for ng-repeat or ng-options.
I know that somehow it lets you pick an object from a list of objects, but 'item' appears in the expression twice and it is not clear to me what the role of that token is in this expression.
Sorry if this is all documented some place which I can not find....
You have an array "items". And you are interating through it with
item in items
As the example you have copied incompletely from this page "https://docs.angularjs.org/api/ng/directive/ngOptions" would normally create a dropdown, there would be now the problem that the "item" object you currently have in your iteration has more fields than just a string to show as label for your dropdown entry. Here is the object again:
$scope.items = [{
id: 1,
label: 'aLabel',
subItem: { name: 'aSubItem' }
}, {
id: 2,
label: 'bLabel',
subItem: { name: 'bSubItem' }
}];
So what do you want to show then? Yeah, you want to show "item.label".
And thats what
item as item.label
does. It tells the loop to use the current "item.label" value as "item" for this specific loop.

JavaScript array of objects conversion

I wasnt exactly sure what i should name this question so feel free to edit the title.
I am running an angular application and using node.js combinded with express and sequlize (for my ORM)
Now as many of you may know when your working with an ORM you want to collect Objects inside of another Object for instance a user object might have a country object inside of it as shown below:
user = {id: 222, username: 'Marc', name: 'Marc Ras', country: {id: 1, code: 'DK', name: 'Denmark'}}
Now this is great. binding all of these objects together makes it alot easier to work with in the frontend.
However the other way around is rather annoying.
Lets for the purpose of demonstration take the above object. but lets add a property an array of items
user.items = [{id: 1 , name:'item1'}, {id: 2, name: 'item2'}]
Now if i wish to add this object to my database i would send the combined object to my express route:
var user = {
id: 222,
username: 'Marc',
name: 'Marc Ras',
country: {id: 1, code:'DK', name: 'Denmark'}
items: [
{id: 1, name: 'item1'},
{id: 2, name: 'item2'}
]
}
And now things get abit messy
Say for instance you have the following table:
user_has_items
Each record in this has an id, user_id, item_id
Now in order to make sure that the objects inside user.items match the table you will now have to make code gymnastic by making loops and editing the above object.
Like as such:
user.items.forEach(function (x) {
x.item_id = x.id;
x.id = null; // To make sure the database does not set the id (since this is auto inc)
x.user_id = user.id;
})
Note the above is of course an example it gets more complicated the bigger your object is!
This process leads to messy code (atleast in my opinion) and since this is not the first time i encounter this problem i was wondering if any of you had any solutions as to what you might do to make this process easier?
I have been looking at lodash to see if they had some way of doing this but sadly i could not find anything that made this easy

angular.js ng-repeat with arrays

i have a simple shopping cart app with angular.js, working quite well.
Customer adds product to the cart, obtaining an object like this (just pasting little) :
shoppingCart {
cartName: "Store",
items: Array[2]
0: Object
name: "product1"
price: 3.5
quantity: 1
sku: "1906"
1: Object
name: "product2"
price: 5
quantity: 1
sku: "1907"
}
Now, people can make different orders, and they're receiving products at the bar before proceeding to checkout and pay).
I have a summary page with an ng-repeat directive to show all products (and + - buttons to make last correction). Once reviewed the cart, the customer click on a order-button.
After ordering, cutsomers can continue shopping and in the same summary page i would like to show, on top, all orders already fulfilled (without + - buttons as the products were already delivered).
i tried moving the content of the shoppingCart object inside another object, but i'm using array.push, and can't figure out how to ng-repeating with an array.
$scope.alreadyDeliveredProducts = {
'itemsAlready' : []
};
$scope.pushmyorders = function (){
$scope.alreadyDeliveredProducts.itemsAlready.push($scope.cart.items);
// and then clear Store
}
now my alreadyDeliveredProducts is like this:
Object {
itemsAlready: Array[2]
0: Array[2] //contains all items of first order
1: Array[3] //contains all items of second order
}
should sound good but now i dont' know how to iterate on this collection.
tried something like this, and it's not correct, but i can0t do better, for now:
<ion-item ng-repeat="ordereditem in alreadyDeliveredProducts.itemsAlready track by $index">
<p> {{ordereditem.name}} </p>
Sorry for this long question, but perhaps (sure) all my strategy to store data could be improved.
Thanks
Problem here:$scope.alreadyDeliveredProducts.itemsAlready.push($scope.cart.items);
Try to change to this: [].push.apply($scope.alreadyDeliveredProducts.itemsAlready, $scope.cart.items);

How to handle data - Windows 8 app

I have looked what seems everywhere for this but maybe it is too obvious and no one mentions it but I am making a windows 8 app and I want the user to be able to edit the data.
Lets say im trying to make a To-Do list, I want the user to be able to add entries. For my current app with dummy static data I have these entries stored in an array in a javascript file. Should I just make the user be able to add/edit/remove entries in the array or is there a different method I should use?
If someone could link me some material to read or an example that shows what I am looking for it would be really helpful.
It really depends on the JavaScript framework you're using. Assuming that you're using Microsoft's own WinJS, what you're looking for is "data binding". This allows you to bind an object or an array to a "control" and have it be automatically updated. Then you just work with the array, adding, removing, sorting items. The data-bind automatically reflects those changes in the template.
Here is a quick example of data-binding from MSDNs own documentation:
<div id="listDiv"
data-win-control="WinJS.UI.ListView"
data-win-options="{ itemDataSource : dataList.dataSource }">
</div>
<script type="text/javascript">
var dataArray = [
{ name: "Marley", species: "dog" },
{ name: "Lola", species: "cat" },
{ name: "Leo", species: "dog" },
{ name: "Izzy", species: "cat" },
{ name: "Ziggy", species: "cat" },
{ name: "Ruby", species: "dog" }
];
var dataList = new WinJS.Binding.List(dataArray);
WinJS.UI.processAll();
</script>
You can see more here: http://msdn.microsoft.com/en-us/library/windows/apps/hh700774.aspx
Each JavaScript framework does this a little bit differently. For example, AngularJS would let you bind an array to a list like this:
<ul>
<li ng-repeat="item in list">{{item.name}}</li>
</ul>
Where 'list' is the name of an array of objects in your scope, item is a single object in the array, and item.name is a string with the name of a single object. The syntax is different, but once again, you would simply manipulate the array and it would be reflected in the resulting HTML.

Categories