VueJS : Get my variable to update when I update my input/select - javascript

Here's basically what my code looks like (or at least part of it, I tried to make it as simple as possible so you can understand what's my problem here.
I have this json of selected ingredients that looks like this:
//var selected_ingredients = [{ 'uuid': uuid, 'nom': 'chicken', 'quantite': '500', 'unite': 'g'}, {...}]
<div
v-for="(ingredient) in selected_ingredients"
:key="ingredient.uuid"
>
<input
type="text"
:value="ingredient.quantite"
>
<select
:value="ingredient.unite"
>
<option
v-for="unite in liste_unites"
:key="unite"
:value="unite"
>{{ unite }}</option>
</select>
</div>
</script>
export default {
data: function () {
return {
categories: [],
tags: [],
ingredients: [],
selected_tags: {},
selected_ingredients: [],
liste_unites: ['pièce', 'mL', 'g']
}
}
</script>
The thing is, I expected that by putting :value="ingredient.quantite", my quantite variable in selected_ingredients would update whenever I update the input field. Which is does not, and I can't seem to understand why. I've been doing some research but I can't tell if my logic is wrong or if I missed a detail.
Can somebody please help me?

Try with 2-way binding v-model:
const app = Vue.createApp({
data() {
return {
selected_ingredients: [{ 'uuid': 1, 'nom': 'chicken', 'quantite': '500', 'unite': 'g'}, { 'uuid': 2, 'nom': 'chicken', 'quantite': '300', 'unite': 'mL'}],
categories: [],
tags: [],
ingredients: [],
selected_tags: {},
liste_unites: ['pièce', 'mL', 'g']
};
},
})
app.mount('#demo')
<script src="https://unpkg.com/vue#3/dist/vue.global.prod.js"></script>
<div id="demo">
<div v-for="(ingredient) in selected_ingredients" :key="ingredient.uuid">
<input type="text" v-model="ingredient.quantite">
<select v-model="ingredient.unite">
<option
v-for="unite in liste_unites"
:key="unite"
:value="unite"
>{{ unite }}</option>
</select>
</div>
{{selected_ingredients}}
</div>

Make sure Vue knows that you want ingredient.quantite to be reactive
Currently you have not done that.
To fix this, try moving your definition of selected_ingredients to within the data function:
data: function () {
return {
selected_ingredients:[{ 'uuid': uuid, 'nom': 'chicken',
'quantite': '500', 'unite': 'g'}, {...}],
categories: [],
tags: [],
ingredients: [],
selected_tags: {},
selected_ingredients: [],
liste_unites: ['pièce', 'mL', 'g']
}
}

Related

Display JSON string array in VUE

I have a JSON data that I'm fetching and I'm having problems display an array in front.
So currently I'm getting this output:
Id: 1
name: Adam
Factors: ["One","Two"]
I want it to be displayed like this:
Id: 1
name: Adam
Factors: One Two
This is how my JSON looks like:
{
"credits": [
{
"id": 1,
"name": "Adam",
"Factors" : ["One", "Two", "Three"]
},
{
"id": 2,
"name": "Jonas",
"Factors" : ["One", "Two", "Three"]
}
]
}
And this is my front code in VUE:
fetching data:
export default {
name: 'app',
data(){
return{
isOpen: false,
id: '',
credits: []
}
},
mounted() {
this.search()
},
methods: {
search() {
if(this.id!="") {
axios
.get(`http://localhost:5041/credits/`, {
params: {
...this.id && {id: this.id}
}
})
.then(response => {
this.credits = response.data
})
}
}
And my div where info is displayed:
<div v-show="isOpen">
<p>Credit ID: {{credits.id}}</p>
<p>Client: {{credits.name}}</p>
<p>DE Factors: <li>{{credits.Factors}}</li></p>
</div>
So, how do I access all of the array elements of the exact post?
This is what I'm getting on display:
Factors: ["One","Two"]
This is what I want to display:
Factors : One Two
You could use a for loop :
<div v-show="isOpen">
<p>Credit ID: {{credits.id}}</p>
<p>Client: {{credits.name}}</p>
<p>DE Factors: <li> <span v-for="Factor in credits.Factors" :key="Factor"> {{ Factor }} </span> </li></p>
</div>
You can use Array.join()
<div v-show="isOpen">
<p>Credit ID: {{ credits.id }}</p>
<p>Client: {{ credits.name }}</p>
<p>DE Factors: {{ credits.Factors.join(' ') }}</p>
</div>

VueJS: Updating component collection data from its child

Given Todo list with filtering:
list.vue:
<script>
import TodoItem from './todo_item.vue';
export default {
components: { TodoItem },
props: ['selectePriority'],
data: {
items: [
{ name: 'Do shopping', priority: 'high' },
{ name: 'Play games', priority: 'low' }
]
},
computed: {
selectedItems: function() {
if(this.selectedPriority == 'all') {
return this.items;
} else {
var selectedPriority = this.selectedPriority;
return this.items.filter(function(item) {
return item.priority == selectedPriority
});
}
}
},
}
</script>
<template>
<div>
<select v-model="selectedPriority">
<option value="all">All</option>
<option value="low">Low</option>
<option value="high">High</option>
</select>
<todo-item
v-for="item in selectedItems"
:name="item.name"
:priority="item.priority"
/>
</div>
</template>
todo_item.vue:
<script>
export default {
props: ['name', 'priority']
}
</script>
<template>
<div>
<p>{{ name }}</p>
<select v-model="priority">
<option value="low">Low</option>
<option value="high">High</option>
</select>
</div>
</template>
html:
<list />
Now, when for example filter is set to all, I change Play games to priority high and change filter to high, I will see only Do shopping, as priority was not updated in items collection and it was re-rendered.
What is proper way to update collection data from child components in Vue.js?
computed properties have the ability to create and return a filtered list.
this example uses lodash
data: {
items: [
{name: 'thing 1', value: 1000},
{name: 'thing 2', value: 50},
{name: 'thing 3', value: 250},
{name: 'thing 4', value: 342},
],
},
computed: {
orderedItems() {
let items = []
return _.orderBy(this.items, 'value', 'desc');
},
}
to update pass the index from orderedItems array into the "this.items" array.
I found some solution that works - instead of passing all params of todo-item into component, pass whole object:
<todo-item
v-for="item in selectedItems"
:item="item"
/>
Then object in parent collection is updated automatically.
Is that a good way of doing that in Vue?

Vue2 dynamic v-model for a group

I am working on a housing form and I am stuck somewhere and I am hoping someone give me a solution to my problem.
So, when you select in a form that your house have 2 floors, then you get to write each floor how many rooms, toilets, balcony etc has..
My issue is to "group" these answers somehow that I could send it to my backend and "read" those answers.
so this is what I did so far:
data() {
return {
flooroptions: [
{
name: 'Rooms',
id: '1',
},
{
name: 'Balcony',
id: '2',
},
{
name: 'Toilets',
id: '3',
},
],
floors: '',
floor1: [],
},
}
and if I loop through like this:
<div class="" v-for="(opt, index) in flooroptions">
<input type="number" name="" value="" v-model="floor1[index]">
</div>
I can see my data using floor1:
{{ floor1 }}
But if in the form someone selects that 1st floor has 2 rooms and does not add any other input than I get to floor1 only 2
How would be better approach for this type of problem ??
PS. Everyfloor will have this flooroptions loop and they can input number of each option for each floor, and I want to be able to read that number correctly..
if I understand correctly, I would...
data() {
return {
flooroptions: [
{
name: 'Rooms',
id: '1',
},
{
name: 'Balcony',
id: '2',
},
{
name: 'Toilets',
id: '3',
},
],
numFloors: 2,
floorData: [
{'Rooms':0, 'Balcony':0, 'Toilets':2},
{'Rooms':2, 'Balcony':1, 'Toilets':0}
],
},
}
and loop through like this:
<div v-for="f in numFloors">
<div class="" v-for="opt in flooroptions">
<input type="number" name="" value="" v-model="floorData[f][opt.name]">
</div>
</div>
or... if you want to pass less data and the id's are know on the backen
data() {
return {
flooroptions: {
1: {
name: 'Rooms'
},
2: {
name: 'Balcony'
},
3: {
name: 'Toilets'
},
},
numFloors: 2,
floorData: [
{1:0, 2:0, 3:2},
{1:2, 2:1, 3:0}
],
},
}
and loop through like this:
<div v-for="f in numFloors">
<div class="" v-for="(opt, i) in flooroptions">
<input type="number" name="" value="" v-model="floorData[f][i]">
</div>
</div>

How can I use ng-repeat to iterate through arrays associated using dynamic keys

I am trying to use ng-repeat to iterate through an array of objects and use each objects ID to look up the data binded to a checklist model.
I have the following javascript object in a project I'm working on:
{
diagnosis: {
mainfractures: [
{
id: "metacarpal",
textinput_id: "metacarpal_text",
title: "5th Metacarpal",
},
{
id: "proximal_phalanx",
textinput_id: "proximal_phalanx_text",
title: "Proximal Phalanx",
},
{
id: "middle_phalanx",
textinput_id: "middle_phalanx_text",
title: "Middle Phalanx",
},
{
id: "distal_phalanx",
textinput_id: "distal_phalanx_text",
title: "Distal Phalanx",
},
{
id: "scaphoid_fracture",
textinput_id: "scaphoid_fracture_text",
title: "Scaphoid Fracture",
}
]
}}
Here is what I have for my checklist model. As the user selects a checkbox, a value is binded to the array associated with that fracture.
$scope.checklists = {
"diagnosis": {
metacarpal: [],
proximal_phalanx: [],
middle_phalanx: [],
distal_phalanx: [],
scaphoid_fracture: []
}
}
Checklist Image Example
Once a users makes a selection similar to the image above the the checklist model for metacarpal should look like this: metacarpal: ["head"]
What I'm trying to do is list each of the users selection in bulletpoint via fracture.id. I'm trying to accomplish it with this piece of code but it's only listed the fracture title so far. is it a problem with trying to interpolate fracture.id into ng-repeat?
<div ng-repeat="fracture in diagnosis.mainfractures">
<div > <!--ng-if="checklists['diagnosis'][fracture.id] > 0"-->
<h4>{{ fracture.title }}</h4>
<div class="row">
<ul type="disc">
<li ng-repeat="selection in checklists['diagnosis'][fracture.id]">
• {{ capitalize(selection) }}
</li>
</ul>
</div>
</div>
</div>
Based on your supplied code, I'd have to say your issue is actually due to JS syntax errors. You're missing commas after each object item and there is a random double quote here scaphoid_fracture"[].
$scope.checklists = {
"diagnosis": {
metacarpal: []
proximal_phalanx: []
middle_phalanx: []
distal_phalanx: []
scaphoid_fracture"[]
}
}
Here is a fully working jsfiddle
Adjusted the code a bit:
capitalize ->
uppercase(https://docs.angularjs.org/api/ng/filter/uppercase)
some syntax errors
But seems that access by dynamic object key inside ng-repeat works pretty correct
https://jsbin.com/rodecosoyo/1/edit?html,js,output
Angular Application
var app = angular.module('arrayid', []);
app.controller('arrayContainerCtrl', function($scope) {
$scope.diagnosis = {
mainfractures: [{
id: "metacarpal",
textinput_id: "metacarpal_text",
title: "5th Metacarpal",
}, {
id: "proximal_phalanx",
textinput_id: "proximal_phalanx_text",
title: "Proximal Phalanx",
}, {
id: "middle_phalanx",
textinput_id: "middle_phalanx_text",
title: "Middle Phalanx",
}, {
id: "distal_phalanx",
textinput_id: "distal_phalanx_text",
title: "Distal Phalanx",
}, {
id: "scaphoid_fracture",
textinput_id: "scaphoid_fracture_text",
title: "Scaphoid Fracture",
}]
};
$scope.checklists = {
"diagnosis": {
metacarpal: ['1', '2'],
proximal_phalanx: ['2', '3'],
middle_phalanx: ['3'],
distal_phalanx: ['4'],
scaphoid_fracture: ['5']
}
};
});
Markup:
<body ng-app='arrayid' ng-controller='arrayContainerCtrl'>
<div ng-repeat="fracture in diagnosis.mainfractures">
<h4>{{ fracture.title }}</h4>
<div class="row">
<ul type="disc">
<li ng-repeat="selection in checklists['diagnosis'][fracture.id]">
• {{ selection | uppercase }}
</li>
</ul>
</div>
</div>
</body>

Getting a a.foreach is not a function error

I am trying to build a multiselect list using angular js. I am getting a weird TypeError: a.foreach is not a function and I can’t seem to figure out when.
js :
var myAppModule = angular.module('multiselect', []);
myAppModule.controller("view", function ($scope) {
$scope.listA = {
values: [{
id: 1,
label: 'aLabel',
subItem: {
name: 'aSubItem'
}
}, {
id: 2,
label: 'bLabel',
subItem: {
name: 'bSubItem'
}
}],
selected: {
name: 'aSubItem'
}
};
})
html:
<select multiple ng-options="item.subItem as item.label for item in listA.values track by item.id" ng-model="listA.selected"></select>
I don’t know what I could be doing wrong. Am I casting something wrong ?
The problem is that since you have added the multiple attribute, the value of the select should be an array. So try something similar to this:
$scope.listA = {
values: [{
id: 1,
label: 'aLabel',
subItem: {
name: 'aSubItem'
}
}, {
id: 2,
label: 'bLabel',
subItem: {
name: 'bSubItem'
}
}],
selected: [{
name: 'aSubItem'
}]
};
You need not to track your values by id. it will do it by default.
<div ng-controller="Main">
<select multiple ng-options="item.subItem as item.label for item in listA.values" ng-model="listA.selected"></select>
</div>
JS Fiddle for your code (Fix):
http://jsfiddle.net/juag4okg/
I was having the same problem. It worked well by creating the static json object as answered above, but did not worked out when i tried to fetched the object or list from the server.
Then i realized my server was not sending the json object and i hadn't convert it to json as well. And when i converted it to json it worked perfectly fine.
So if you are having similar problem to display the select options (muliple or single) from the server side data this process might help you.
here is the link to angular angular.toJson() function.

Categories

Resources