I'm building a checklist app as a way to learn Vue.
I've got a nested object with no defined max depth, and I want to display a status on all items that is based on if the item itself is checked, and if (some of) its children are checked (if there are any).
I would like this to happen without an extra property in the object, since these items are going to be draggable and I would like it to update the status automatically after some items moved.
This is my data:
[{
name: "item 1",
checked: 0,
items: [
{
name: "subitem 1",
checked: 0,
items: [
//etc...
]
},
{
name: "subitem 2",
checked: 0,
items: [
//etc...
]
}
]
}]
The app looks like this:
<div id="app">
<checkin-list :checklist="items"></checkin-list>
</div>
The checkin-list components template looks like this:
<li v-for="item in checklist">
<div :status="childstatus(item)">
<input type="checkbox" :id="'check_' + index" v-model="item.checked">
<label :for="'check_' + index">{{ item.name }}</label>
</div>
<checkin-list :checklist="item.items"></checkin-list>
</li>
The childstatus function takes an item and loops through all its children to check if some or all items are checked.
When I check an item on level 4, it only updates level 3 and 4; it doesn't bubble all the way to the top. I've tried to $emit the event to its parents, but I don't know how to force the childstatus to be recalculated on those items. I'm not sure if this type of event bubbling is correct here or if computed or watched properties can be helpful here.
I'm curious about what you would suggest here.
Related
I wanted to ask if there is any way to make a dropdown menu in react using .map() and .filter(),
like for instance let's say that i have this file :
Data.js
export const NavigationMenu = [
{
id: 1,
title: "header item 1",
},
{
id: 2,
title: "header item 2",
}
];
export const NavigationDropMenu = [
{
id: 1,
title: "drop item 1",
parent: "header item 1",
},
{
id: 2,
title: "drop item 1",
parent: "header item 2",
}
];
what i want to do is to first map the items from the first list like this
<li className="header__menu__item">
{item.title}
</li>
))}
and inside of that i want to make another map for the dropmenu, which will fetch items from the second list but to use filter to show only elements that contain that element as a trait.
so to make it simpler, I want to know if it is possible to make a dropdown menu using .map() and .filter().
thank you.
StackBlitz example
I'm trying to loop dynamic values to create radio button items on my form. I have managed to display the three radio buttons coming from my data:
radiot: [
{
section: "yes",
sectionCode: "1"
},
{
section: "no",
sectionCode: "2"
},
{
section: "maybe",
sectionCode: "3"
}
]
The problem is I cant display the option of "section".
e.g.
<div class="form-check-inline" *ngFor="let item of personal.radioButtons.radiot; let i = index">
<label for="yes" class="col-12 customradio"
><span>{{item[i].section}}</span>
<input value="{{item[i].section}}" id="{{item[i]}}" type="radio" [formControlName]="i"/>
<span class="checkmark"></span>
</label>
</div>
What am I doing wrong? getting the error - Cannot read property 'section' of undefined
StackBlitz example
You don't need to use i in *ngFor you already have reference to the object at that position.
So for the first iteration your item would be
{
section: "yes",
sectionCode: "1"
}
So you can just do item.section - no need for the index position.
<span>{{item.section}}</span>
Change your template from [formControlName] to formControlName
<label for="{{item.section}}" class="col-12 customradio"
><span>{{item.section}}</span>
<input value="{{item.section}}" name="formGroupName" id="{{item.section}}" type="radio" formControlName="radiot"/>
<span class="checkmark"></span>
</label>
As it is currently written you were telling angular to look for a variable named radiot which is undefined, but what it needs is a string so it can look for it as a property on the current form object
You should put = instead of :
radiot = [
{
section: "yes",
sectionCode: "1"
},
{
section: "no",
sectionCode: "2"
},
{
section: "maybe",
sectionCode: "3"
}
];
looking around for a solution for my problem!
I try to make Vue.Draggable work with VueFire. I have a few lists with cards that can be dragged between them, sorted, cloned and so on. While the lists are populated with cards Vue.Draggable works perfectly, it watches for changes, triggers events like magic.
This is the working JSON:
categories: [{
name: "todo",
cards: ["second","first","second"]
},{
name: "doing"
cards: ["first","fourth","second"]
},{
name: "done",
cards: ["second", "fourth","first","third"]
}]
The problem comes when one o the lists is empty. We all know that Firebase doesn't store empty properties that's why Vue.Draggable can't watch for a property that doesn't exist. For example like this:
categories: [{
name: "todo",
cards: ["second","first","second"]
},{
name: "doing"
// missing cards property because it's empty
},{
name: "done",
cards: ["second", "fourth","first","third"]
}]
The cards property should be filled with values by dragging items to the list, but because cards doesn't exist Vue.Draggable can't watch for changes in that list and can't trigger events.
Is there a way to create some kind of placeholder or middleware to simulate that empty array? Or what are other possible solutions in this case?
Here's a small JSFiddle.
Thank you!
Why don't you initialize the cards property if nothing is returned from firebase?
categories: [{
name: "todo",
cards: ["second","first","second"]
},{
name: "doing",
cards: firebaseCollectionProperty || []
},{
name: "done",
cards: ["second", "fourth","first","third"]
}]
New to angular! So two sets of data. One containing meals, one containing entries. Each meal can have several entries, but each entry only relates to one meal.
In my data, the meals table has an Id, and in the entries table, there is a reference to the meal id with a meal_id property.
meal:
{
id: 4,
user_id: 3,
date: 12345678,
name: "soFood",
location: "Litchfield, CT",
rating: 1,
notes: "This is a note here",
image: "http://www.image.com"
},
entry:
{
id: 3,
meal_id: 4,
name: "Fet UP",
rating: 0,
notes: null,
image: "http://not.anote.here"
}
At the moment I am able to repeat the meals. I'd like to be able to uniquely repeat the entries for an individual meal.
So for a list of meals, be able to click on one and have a list of its unique entries show up.
I know I have to somehow get the meal_id to compare to the id of the meals but I'm unsure how to use ng-repeat doing that?
You will first affect the current meal to a variable in your upper ng-repeat, i.e. ng-repeat="meal in meals". This current meal is known in the scope of the ng-repeat directive. You can use it to filter an entries array and use the result in an inner ng-repeat :
<li ng-repeat="meal in meals">
<div ng-repeat="entry in (entries | filter : {'meal_id': meal.id})">
</div>
</li>
Question
I'm interested in the properties of $$hashkey on angular arrays/objects.
Would each generated hashkey be the same each time you reload a
page; a quick test tells me yes but I somewhat assumed it
wouldn't?
If you updated/added to the existing array, would the old hashkey's
stay consistent?
If the above is true, is there a way to fetch from an array using
the hashkey? - of cause I could roll my own but before I recreate the wheel I thought I'd ask.
Example:
Views would include:
form data (example has 1 form)
element data (example has 2 elements)
element options data (example has 2 options per element)
Fetch method:
angular.get($$hashkey);
You would then pass the hashkey of the element and it would return a reference to that array inside the full array.
Lastly the data would be:
{
form_id: 1
form_desc: 'xxx',
form_name: 'name 1',
Elements: [
{
element_id: 1,
element_name: 'element1',
default_value: null,
disabled: "0",
element_type: "image",
ElementOptions: [
{
show: false,
sort_order: 0,
value: "ar",
},
{
show: true,
sort_order: 1,
value: "rw",
}
],
},
{
element_id: 2,
element_name: 'element2',
default_value: null,
disabled: "0",
element_type: "image",
ElementOptions: [
{
show: false,
sort_order: 0,
value: "ar",
},
{
show: true,
sort_order: 1,
value: "rw",
}
],
}
]
}
$$hashkeys will only be computed for functions and objects so if you wish to track anything that isn't one of those types then you have that limitation.
$$Hashkeys look like ...
(function||object): N
...
Where N is just an incremental value being adjusted + 1 for each $$HashKey computed.
So, in many cases this could be the same value across page loads. But loading data that is asynch, will cause differences when multiple data sources are being queried as part of page initialization and order of return cannot be guranteed. In cases like that you would have to marshall all your asynch data and then assign that data to your scope in a specific order to ensure consistent $$hashkeys.
Moving items around in an array that is linked to our DOM (via ng-repeat) will not change that items $$hashkey. Deleting it and re-adding it will.
I would not use $$Hashkey for my own housekeeping as it is intended to be internal to AngularJS.
I've used this internal private property when I had no identifiers.
I think, it's pretty usable, but not recommended.