Binding object to checkbox value in Vuejs - javascript

So normal checkboxes in vuejs allows you to bind a model to it.
When this model has the values from checkboxes pre filled, those particular checkboxes appear checked.
<tr v-for="user in users">
<td>{{ user.name }}</td>
<td>
<input type="checkbox" v-model="selectedUsers" v-bind:value="{ id: user.id }">
</td>
<td>
<input type="checkbox" v-model="selectedUsers" value="{{ user.id }}">
</td>
</tr>
However you don't get the same behaviour when you bind the checkbox value to an object.
Following is the snippet:
new Vue({
el: '#app',
data: {
users: [{
"id": "1",
"name": "Shad Jast",
"email": "pfeffer.matt#yahoo.com"
}, {
"id": "2",
"name": "Duane Metz",
"email": "mohammad.ferry#yahoo.com"
}, {
"id": "3",
"name": "Myah Kris",
"email": "evolkman#hotmail.com"
}, {
"id": "4",
"name": "Dr. Kamron Wunsch",
"email": "lenora95#leannon.com"
}, {
"id": "5",
"name": "Brendon Rogahn",
"email": "verlie.buckridge#yahoo.com"
}],
selectedUsers: [{
"id": "1"
}, "1"]
}
})
<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>
<div id="app">
<h4>User</h4>
<div>
<table>
<tr>
<th>Name</th>
<th></th>
<th></th>
</tr>
<tr v-for="user in users">
<td>{{ user.name }}</td>
<td>
<input type="checkbox" v-model="selectedUsers" v-bind:value="{ id: user.id }">
</td>
<td>
<input type="checkbox" v-model="selectedUsers" value="{{ user.id }}">
</td>
</tr>
</table>
</div>
<span>Selected Ids: {{ selectedUsers | json }}</span>
</div>

I have done it the following way, please suggest better ways, if any:
new Vue({
el: '#app',
data: {
users: [{
"id": "1",
"name": "Shad Jast",
"email": "pfeffer.matt#yahoo.com"
}, {
"id": "2",
"name": "Duane Metz",
"email": "mohammad.ferry#yahoo.com"
}, {
"id": "3",
"name": "Myah Kris",
"email": "evolkman#hotmail.com"
}, {
"id": "4",
"name": "Dr. Kamron Wunsch",
"email": "lenora95#leannon.com"
}, {
"id": "5",
"name": "Brendon Rogahn",
"email": "verlie.buckridge#yahoo.com"
}],
previousUsers: [{
"id": "2"
}, {
"id": "5"
}, "1", "5"],
updatedUsers: []
},
methods: {
check: function(user_id) {
var checked = false;
for (i = 0; i < this.previousUsers.length; i++) {
if (this.previousUsers[i].id == user_id) {
this.previousUsers.splice(i, 1)
return true
}
return false;
}
}
}
})
<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>
<div id="app">
<h4>User</h4>
<div>
<table>
<tr>
<th>Name</th>
<th></th>
<th></th>
</tr>
<tr v-for="user in users">
<td>{{ user.name }}</td>
<td>
<input type="checkbox" v-model="updatedUsers" v-bind:value="{ id: user.id }" checked="{{check(user.id)}}">
</td>
<td>
<input type="checkbox" v-model="updatedUsers" value="{{ user.id }}">
</td>
</tr>
</table>
</div>
<span>Selected Ids: {{ updatedUsers | json }}</span>
</div>

Related

How to generate nested Json object from inputs?

I need to generate following Json Object daynamically from inputs
{
"name":"USA",
"parents": [
{
"state":"California",
"id":"12",
"child":[
{
"city":"Los Angeles",
"id":"1"
},
{
"city":"San Francisco",
"id":"2"
}
]
},
{
"state":"Texas",
"id":"33",
"child":[
{
"city":"Dallas",
"id":"3"
},
{
"city":"Houston",
"id":"4"
}
]
}
]
}
from this Table of inputs
<table id="tTypeTable" class="table table-bordered" hidden="hidden" >
<tr>
<th><a class="btn btn-primary" onclick="add_tTypeParentField();"></th>
</tr>
<!-- ko foreach: {data: tTypeParentFields, as: 'tParentField'} -->
<tr>
<td>
<table class="table table-hover" >
<tr>
<th> State </th>
<th> </th>
</tr>
<tr title="tParentRow" >
<td>
<input id="state" data-bind="value: tParentField[0]"
onblur="createJSON()"/>
</td>
<td>
<input id="value" data-bind="value: tParentField[0]"
onblur="createJSON()"/>
</td>
</tr>
</table>
<table id="tChild" class="table table-hover" >
<tr>
<th> City </th>
<th> </th>
<th> <a id="childAdd" onclick="addChild(this);"></th>
</tr>
<tbody>
<tr title="tChildRow" id="tChildRow">
<td>
<input id="cityName" onblur="createJSON()"/>
</td>
<td>
<input id="cityValue" " onblur="createJSON()"/>
</td>
<td>
<a id="removeChild" onclick="deleteChild(this)" ></a>
</td>
</tr>
</tbody>
</table>
<td> <a data-bind="click: removeTTypeParentField" ></a></td>
</td>
</tr>
<!-- /ko -->
</table>
<div class="col-md-11 ">
<textarea class="form-control" id="requestData" ></textarea>
</div>
there is no problem with adding new row of inputs. I have used Knockouts for addding Parent table and used jQuery for adding child table. it's working well.
The problem is that generating Json child Object (cities).
I have tried to get value of inputs and generate Json Object in textare like this
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script th:inline="javascript">
function createJSON() {
var jsonObj = [];
$(document).ready(function() {
var valueTypeTChild = [];
var valueTypeTParent = [];
$("tr[id=tParentRow]").each(function() {
$(this).find('tr[id=tChildRow]').each(function () {
child = {
city: $(this).find('#cityName').val(),
id: $(this).find('#cityValue').val()
};
valueTypeTChild.push(child);
});
parent = {
city:$(this).find('#state').val(),
id:$(this).find('#value').val(),
child: valueTypeTChild
};
valueTypeTParent.push(parent);
);
inputItem = {
"name":"Country",
parents: valueTypeTParent
};
jsonObj.push(inputItem);
});
$('#requestData').val(JSON.stringify(jsonObj));
console.log(JSON.stringify(jsonObj));
</script>
But I'm getting this
{
"name": "USA",
"parents": [
{
"state": "California",
"id": "12",
"child": [
{
"city": "Los Angeles",
"id": "1"
},
{
"city": "San Francisco",
"id": "2"
},
{
"city": "Dallas",
"id": "3"
},
{
"city": "Houston",
"id": "4"
}
]
},
{
"state": "Texas",
"id": "33",
"child": [
{
"city": "Los Angeles",
"id": "1"
},
{
"city": "San Francisco",
"id": "2"
},
{
"city": "Dallas",
"id": "3"
},
{
"city": "Houston",
"id": "4"
}
]
}
]
}
You are giving every state the same city array without clearing it.
Move var valueTypeTChild = []; inside the $("tr[id=tParentRow]").each(function() { loop.

handlebar select box populate

my HTML code,
I want each user role is selected next to the select box of each user name,
inside the each loop of role i cant able to access the role of parent user node,
is it possible to compare the role id of user node with roles node roleid and when its equal, the option will be selected
<table>
<tr>
<p>peter is employee</p>
<p>john is admin</p>
<p>michel is manager</p>
</tr>
{{#user}}
<tr>
<td>
<input type="text" value="{{name}}">
</td>
<td>
<select>
{{#each ../roles}}
<option value="{{roleid}}">{{value}}</option>
{{/each}}
</select>
</td>
</tr>
{{/user}}
This is may Json
var data = {
"user": [
{ "name": "peter", "role": 1 },
{ "name": "john", "role": 2 },
{ "name": "michel", "role": 3 }
],
"roles": [
{ "roleid": 1, "value":"manager"},
{ "roleid": 2, "value":"employee"},
{ "roleid": 3, "value":"admin"}
]
};
fiddle url https://jsfiddle.net/Manu_S/egbwbfav/2/
thanks
You can access the parent node values and compare in your select box.
Please follow the Jsfiddle working that
https://jsfiddle.net/gsubbarao/nz0bc0pq/
<script id="t" type="text/x-handlebars">
<table>
<tr>
<p>peter is employee</p>
<p>john is admin</p>
<p>michel is manager</p>
</tr>
<tr>
<td> </td><td></td><td></td>
</tr>
{{#user}}
<tr>
<td>
<input type="text" value="{{name}}">
</td>
<td>
<select>
{{#each ../roles}}
<option value="{{roleid}}"
{{#ifCond ../role roleid}}
selected
{{/ifCond}}
>
{{value}}
</option>
{{/each}}
</select>
</td>
</tr>
{{/user}}
</script>
var data = {
"user": [
{ "name": "peter", "role": 2 },
{ "name": "john", "role": 3 },
{ "name": "michel", "role": 1 }
],
"roles": [
{ "roleid": 1, "value":"manager"},
{ "roleid": 2, "value":"employee"},
{ "roleid": 3, "value":"admin"}
]
};
Handlebars.registerHelper('ifCond', function(v1, v2, options) {
if(v1 === v2) {
return options.fn(this);
}
return options.inverse(this);
});
var t = Handlebars.compile($('#t').html());
$('body').append(t(data));

Angularjs and automatically generated SELECT tags

I have a bit of a problem, I have an API that provides me with products, and each product has multiple options, like so :
[
{
"name": "Product 1",
"options": [
{
"name": "Product 1 all options",
"price": 2000
}, {
"name": "Product 1 no option",
"price": 1400
}
]
}, {
"name": "Product 2",
"options": [
{
"name": "Product 2 all options",
"price": 3000
}, {
"name": "Product 2 no option",
"price": 1900
}
]
}];
Now I present it as so :
<tbody>
<tr ng-repeat="product in products">
<td>{{ product.name }}</td>
<td>
<select class="form-control">
<option
ng-repeat="option in product.options"
data-price="{{ option.price }}">{{ option.name }}</option>
</select>
</td>
<td>HERE I WANT TO DISPLAY THE SELECTED option.price +/- VAT</td>
</tr>
</tbody>
Now as you may notice, the <select> tag itself is inside a ng-repeat, so it can be infinitely repeated, depending on the number of products I have; I can't bind the select to any ng-model because I may accidentally bind many <select>'s to the same model.
Now for each <select>, I have to display the price +/- a VAT in the third <td>, that corresponds to the selected option. Is there any way of doing that with angularjs? I don't want to go plain JS/jQuery.
You can use the product variable as the model for the select. When the value changes it will also be updated outside the select as well.
An example would be:
app.controller('MainCtrl', function($scope) {
$scope.products = ['a', 'b', 'c', 'd'];
});
<body ng-controller="MainCtrl">
<div ng-repeat="product in products">
<input ng-model="product">
<div>{{product}}</div>
</div>
</body>
You can find a working plnkr here.
A working example using your data. It's making a new field in your product called selectedPrice just to store the selected option.
app.controller('MainCtrl', function($scope) {
$scope.products = [{
"name": "Product 1",
"options": [{
"name": "Product 1 all options",
"price": 2000
}, {
"name": "Product 1 no option",
"price": 1400
}]
}, {
"name": "Product 2",
"options": [{
"name": "Product 2 all options",
"price": 3000
}, {
"name": "Product 2 no option",
"price": 1900
}]
}];
});
<table>
<tbody>
<tr ng-repeat="product in products">
<td>{{ product.name }}</td>
<td>
<select class="form-control" ng-model="product.selectedPrice">
<option ng-repeat="option in product.options" value="{{ option.price }}">{{ option.name }}</option>
</select>
</td>
<td>{{product.selectedPrice}}</td>
</tr>
</tbody>
</table>
A working example of that can be found here.
Alternative to #toskv you can also avoid option tag altogether.
<tr ng-repeat="product in products">
<td>{{ product.name }}</td>
<td>
<select class="form-control" ng-model="product.selectedPrice" ng-options="option.price as option.name for option in product.options track by option.name">
</select>
</td>
<td>{{product.selectedPrice}}</td>
</tr>
see this

angularJS nesting ng-repeat

I have data in the following format.
[
{
"id": "1",
"quizId": "2",
"question": "What team is Messi playing ?",
"quiz": [
{
"id": "2",
"categoryId": "67",
"name": "Football Quiz",
"quizsize": "0"
}
],
"answers": [
{
"id": "1",
"questionId": "1",
"name": "Barcelona",
"correct": "1"
},
{
"id": "2",
"questionId": "1",
"name": "M.City",
"correct": "0"
},
{
"id": "3",
"questionId": "1",
"name": "Real Madrid",
"correct": "0"
},
{
"id": "4",
"questionId": "1",
"name": "Liverpool",
"correct": "0"
}
]
}
]
I trying to display it in a table.
Each question(the root) is a row, the for one td I get the quiz.name and then I'm trying to display the answers.name as well.
<table class="table table-striped">
<tr>
<th>Title</th>
<th>Category</th>
<th>Answer 1</th>
<th>Answer 2</th>
<th>Answer 3</th>
<th>Answer 4</th>
</tr>
<tr ng-repeat="question in questions">
<td>{{ question.question}}</td>
<td>{{ question.quiz[0].name }}</td>
<td ng-repeat="answer in question.answers">
<td>{{ answer.name}}</td>
</td>
</tr>
</table>
The second ng-repeat does not display anything.
I also tried answer[0].name.
Your current HTML is invalid as per standards.
td element can not be nested, you should use different element to display content inside td like div or span
Markup
<tr ng-repeat="question in questions">
<td>{{ question.question}}</td>
<td>{{ question.quiz[0].name }}</td>
<td ng-repeat="answer in question.answers">
<div>{{ answer.name}}</div>
</td>
</tr>

VueJs: Focus on Input using v-el Directive inside v-repeat Directive

I display a list by using the v-repeat directive.
http://jsfiddle.net/ftc9ev7p/1/
Please notice the dynamically created argument of the v-el directive, which is made of
v-el="inputField{{task.id}}"
or alternatively
v-el="{{'inputField' + task.id }}"
Still it doesn't get recognized, since I get:
Uncaught TypeError: Cannot read property 'focus' of undefined
I want to click the edit button and have the according input field focused on.
A similar syntax works, when I dynamically add a css class. Just uncomment the line with the .focus() and click "edit".
new Vue({
el: '#tasks',
data: {
"tasks": [{
"id": 25,
"body": "Slack Noooo Yes",
"completed": true,
"created_at": "2015-08-05 17:00:26",
"updated_at": "2015-08-05 17:00:26"
}, {
"id": 27,
"body": "And",
"completed": false,
"created_at": "2015-08-05 17:22:14",
"updated_at": "2015-08-05 17:22:14"
}, {
"id": 28,
"body": "Happiness",
"completed": false,
"created_at": "2015-08-05 17:22:16",
"updated_at": "2015-08-05 17:22:16"
}, {
"id": 29,
"body": "Love",
"completed": true,
"created_at": "2015-08-06 07:45:02",
"updated_at": "2015-08-06 07:45:02"
}],
newTask: ''
},
methods: {
editTask: function(task) {
var inputField = 'inputField' + task.id;
alert(inputField);
var self = this;
self.$$.inputField.focus();
document.querySelector(".task" + task.id).className += " edit";
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/0.12.8/vue.min.js"></script>
<table class="table" id="tasks">
<thead>
<tr>
<th>Task</th>
<th>Edit</th>
<th>Options</th>
</tr>
</thead>
<tbody>
<tr v-repeat="task: tasks">
<td class="todo">
<span class="task{{ task.id }}" v-on="dblclick: editTask(task)">
{{ task.body }}
</span>
</td>
<td>
<input type="text" class="editInputField" v-el="inputField{{ task.id }}" value="{{ task.body }}" v-on="keyup:editTask(task) | key 'enter'">
</td>
<td>
<button class="btn btn-xs btn-primary" v-on="click: editTask(task)">Edit</button>
</td>
</tr>
</tbody>
</table>
Here is the jsfiddle:
http://jsfiddle.net/ftc9ev7p/1/
You don't really have to number the elements by v-el since you can get a child ViewModel created by v-repeat. The official guide is on http://vuejs.org/guide/events.html#Invoke_Handler_with_Expression.
You can pass this to editTask in v-on and then you can get the child ViewModel by the first argument:
<div v-repeat="task: tasks">
<span class="task" v-el="label" v-on="dblclick: editTask(this)">
<input type="text" v-el="inputField" class="editInputField" value="{{ task.body }}">
</div>
editTask: function (task) {
task.$$.inputField.focus();
task.$$.label.className += " edit";
}
Also you can get the targetVM by using event.targetVM in the function without the need of passing this to your function.
<div v-repeat="task: tasks">
<span class="task" v-el="label" v-on="dblclick: editTask()">
<input type="text" v-el="inputField" class="editInputField" value="{{ task.body }}">
</div>
editTask: function () {
event.targetVM.$$.inputField.focus();
event.targetVM.$$.label.className += " edit";
}
JS Fiddle: http://jsfiddle.net/n1ef18uq/1/

Categories

Resources