Vue JS how to bind checkboxes? - javascript

How do we bind checkboxes value using vue js expression ? Below i have the data the filteroptions object and i manage to bind the value to the #html1 i have put below.
What I want to know is how can i bind the checked values to #html2 ? the selected values from the drpdown menu in #html1
As you can see on my filter by on html2 it is not dynamic.
Thank you.
html1
<div class="mh-filter-options">
<div class="filter-content">
<ul class="nav nav-pills">
<li class="dropdown" v-for="(opt, item) in filterOptions" :key="item">
<a class="dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true"
aria-expanded="false"> {{item}}</a>
<div class="dropdown-menu">
<a href="#" v-for="i in opt" :key="i.value">
<div class="inner">
<div class="checkbox">
<label class="filter-label-item">
<input type="checkbox" :data-prop="opt" :value=i.value />
<span class="cr"><i class="cr-icon fa fa-check"></i></span>
<span>{{i.value}} <span class="badge badge-dark">{{i.count}}</span></span>
</label>
</div>
</div>
</a>
</div>
</li>
</ul>
</div>
</div>
html 2
<div class="filtered-by">
<div class="filter-title">Filtered By: </div>
<div>
<div class="filter-item">
Year: <span> 2019 </span>
<i class="fas fas- fa-times"></i>
</div>
<div class="filter-item">
Model: <span> Escape </span>
<i class="fas fas- fa-times"></i>
</div>
<div class="filter-item">
Price range: <span> $5000-$10000 </span>
<i class="fas fas- fa-times"></i>
</div>
</div>
<div class="clear-all-filter">
Reset Filters
</div>
</div>
Method
setFilters() {
this.filterOptions = {
year: [{ value: '2019', checked: true, count: 10 }, { value: '2013', checked: false, count: 99 }, { value: '2017', checked: true, count: 10 }],
model: [{ value: 'Explorer', checked: true, count: 8 }, { value: 'Ram 1500', checked: false, count: 4 }, { value: 'Piloto', checked: false, count: 10 }],
priceRange: [{ value: '$10,000-$20,000', checked: false, count: 5 }, { value: '$20,000-$30,000', checked: false, count: 22 }, { value: '$30,000-$40,000', checked: false, count: 10 }],
mileage: [{ value: '1-1000', checked: false, count: 10 }, { value: '1001-2000', checked: false, count: 64 }, { value: '2001-3000', checked: false, count: 10 }],
bodyStyle: [{ value: 'Crew Cab Pickup', checked: false, count: 13 }, { value: 'Quad Cab Pickup', checked: false, count: 9 }, { value: 'Sport Utility', checked: true, count: 2 }]
}
},

You should bind checkboxes with v-model, which takes a boolean value. So in your case it might be <input type='checkbox' v-model='i.checked'>
I'm not sure I totally follow your code, particularly the setFilters() method, but the principal of Vue is that you encapsulate all your page state in a model, then html2 just looks at the model value that's 2-way bound to the checkbox. Does that make sense ?

Related

Error while looping nested array of objects using pure javascript

I want to display tasks array of object values(given below) using javascript. When I iterate through tasks array and render elements, it's okay. But I want to have loop inside outer loop to display sub tasks of each task. But, if I loop through each sub task as given below, then it throws error in the console as task.subTasks.forEach(...) is not a function
const tasks = [
{
id: 0,
description: "task 1",
subTasks: [
{ id: 0, description: "subtask 1" },
{ id: 1, description: "subtask 2" },
],
},
{
id: 1,
description: "task 2",
subTasks: [
{ id: 0, description: "subtask 3" },
{ id: 1, description: "subtask 4" },
],
},
{
id: 2,
description: "task 3",
subTasks: [
{ id: 0, description: "sub task 5" },
{ id: 1, description: "sub task 6" },
],
},
];
const accordion = document.querySelector("#accordion");
function displayTasks() {
tasks.forEach((task, index) => {
let html = `
<div class="accordion-item" id="${index}">
<div class="todo-task">
<i class="far fa-circle"></i>
<input value="${task.description}" placeholder="Update your task" type="text">
<i class="fas fa-pen"></i>
<i class="fa fa-trash"></i>
<i class="fas fa-chevron-down"></i>
</div>
<div class="todo-sub-tasks">
`
task.subTasks.forEach((item,index)=>{
<div class="todo-sub-task">
<i class="far fa-circle"></i>
<input placeholder="Update your sub task" type="text" />
<i class="fas fa-pen"></i>
<i class="fa fa-trash"></i>
</div>
})
`
</div>
</div>
`;
accordion.insertAdjacentHTML("beforeend", html);
});
}
displayTasks();
Your html variable needs to be declared outside the loop call, so that you can feed the result of the loop into it.
An inner variable is used in the example below to compile the required HTML for each task.
const tasks = [{
id: 0,
description: "task 1",
subTasks: [
{ id: 0, description: "subtask 1" },
{ id: 1, description: "subtask 2" }
]
}, {
id: 1,
description: "task 2",
subTasks: [
{ id: 0, description: "subtask 3" },
{ id: 1, description: "subtask 4" }
]
}, {
id: 2,
description: "task 3",
subTasks: [
{ id: 0, description: "sub task 5" },
{ id: 1, description: "sub task 6" }
]
}];
const accordion = document.querySelector("#accordion");
function displayTasks() {
const html = tasks.map((task, index) => {
let taskHTML = `
<div class="accordion-item" id="${index}">
<div class="todo-task">
<i class="far fa-circle"></i>
<input value="${task.description}" placeholder="Update your task" type="text">
<i class="fas fa-pen"></i>
<i class="fa fa-trash"></i>
<i class="fas fa-chevron-down"></i>
</div>
<div class="todo-sub-tasks">
`;
taskHTML += task.subTasks.map((subTask) => (`
<div class="todo-sub-task">
<i class="far fa-circle"></i>
<input value="${subTask.description}" placeholder="Update your sub task" type="text" />
<i class="fas fa-pen"></i>
<i class="fa fa-trash"></i>
</div>
`));
taskHTML += `
</div>
</div>
`;
return taskHTML;
});
accordion.insertAdjacentHTML("beforeend", html);
}
displayTasks();
<div id="accordion"></div>

Dynamically populated bootstrap multiselect not displaying options when in a dropdown

When I place a dynamically populated multiselect in a dropdown overlay, the multiselect's dropdown does not display when clicked. The exact same multiselect works just fine when it's not in a dropdown. See a fiddle that reproduces the issue here http://jsfiddle.net/yhnukfsz/6/ (started with the answer to this question).
The broken multiselect in question:
<div class="btn-group">
<button type="button" id="dropBtn" class="btn btn-primary btn-lg dropdown-toggle" data-toggle="dropdown">
Dropdown <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li>
<form>
<select class="form-control" id="mult2" multiple="multiple">
</select>
<button>
foobar
</button>
</form>
</li>
</ul>
</div>
And the JS:
$('.dropdown-menu').on('click', function(event) {
event.stopPropagation();
});
$('.selectpicker').selectpicker({
container: 'body'
});
$('body').on('click', function(event) {
var target = $(event.target);
if (target.parents('.bootstrap-select').length) {
event.stopPropagation();
$('.bootstrap-select.open').removeClass('open');
}
});
setUpMultiselect('#mult1');
setUpMultiselect('#mult2');
function setUpMultiselect(id) {
$(id).multiselect({
enableFiltering: true,
includeFilterClearBtn:false,
enableCaseInsensitiveFiltering: true,
selectAllJustVisible : true,
includeSelectAllOption : true,
nonSelectedText:"Filter ...",
numberDisplayed : 1
});
const options = [
{
title: 'title1', label: 'label1', id: 'id1', selected: true,
},{
title: 'title2', label: 'label2', id: 'id2', selected: true,
},{
title: 'title3', label: 'label3', id: 'id3', selected: true,
}]
$(id).multiselect('dataprovider', options);
$(id).multiselect('rebuild');
}
$('#dropBtn').click(() => {
setTimeout(() => {
setUpMultiselect('#mult1');
setUpMultiselect('#mult2');
}, 500)
})
Additional things I've tried that haven't fixed the issue include rebuilding/reinitializing the multiselect on the dropdown click event with and without a delay.

grocery cart on Angular

I create add-to-cart app.
Want to click each item and add it to cart.
But firstly I need to click button 'add to cart' and increase its value with every click.
As I added ng-repeat, I don't know how to write a function that will be responsible for adding separate item.
angular.module('TransactionApp', [])
.controller('TransactionsCtrl', function($scope) {
$scope.title = 'Online-store';
$scope.itemsArray = [
{ price: 50, name: "Whey protein", img: 'img/item-1.png', quantity: 0},
{ price: 60, name: "Protein bar", img: 'img/item-2.png', quantity: 0 },
{ price: 35, name: "BCAA", img: 'img/item-3.png', quantity: 0 },
{ price: 50, name: "Whey protein", img: 'img/item-1.png', quantity: 0 },
{ price: 60, name: "Protein bar", img: 'img/item-2.png', quantity: 0 },
{ price: 80, name: "BCAA", img: 'img/item-3.png', quantity: 0 }
];
// $scope.count = 0;
$scope.addTo = function(){
}
});
here is html:
<h2 class="title">{{title}} <i class="em em-shopping_bags"></i></h2>
<div class="container">
<div class="row">
<div class="col-lg-4 col-md-2 col-sm-6">
<div class="card" style="width: 18rem;" ng-repeat='item in itemsArray'>
<img class="card-img-top" ng-src={{item.img}} alt="Card image cap">
<div class="card-body">
<h5 class="card-title"></h5>
<p class="card-text">{{item.name}}</p>
<p class="price">{{ item.price | currency }}</p>
<i class="em em-shopping_trolley"></i> Add to cart <span class="number">{{ item.quantity }}</span>
</p>
</div>
</div>
</div>
</div>
</div>
Pass the item to controller with addTo(item):
<a href="#" class="btn btn-warning" ng-click="addTo(item)">
<i class="em em-shopping_trolley"></i>
Add to cart
<span class="number">{{ item.quantity }}</span>
</a>
after your addTo accepts a parameter:
$scope.addTo = function(item){ // 'item' is a reference to an element in itemsArray
item.quantity++;
}
I believe each of your item in view has its own Add to Cart Button against it and I also believe you want to increase the quantity property of each of the item each time a user clicks the button against that item.
For that all you have to do is pass the item to addTo() method like :-
<i class="em em-shopping_trolley"></i> Add to cart <span class="number">{{ item.quantity }}</span>
and modify the method definition in controller
$scope.addTo = function(var item){
item.quantity++;
}

Vue how to traverse the list correctly?

I just writed the vue simple code, But unable to follow the HTML effect. After traversal rendering a bit wrong. If gift object is no, for example the goods object has two data, goods_b1 + goods_b2. But i want to follow the HTML effect. Go to the HTML still. And go to the vue loops.
I want to the this effect:
Look at the javascript:
var app = new Vue({
el: "#app",
data: {
list: [{
id: 1,
name: 'A',
goods: [{
name: "goods_a1"
}],
gift: [{
name: "gift_a1",
}]
}, {
id: 2,
name: 'B',
gift: [],
goods: [{
name: "goods_b1"
}, {
name: "goods_b2"
}],
}, {
id: 3,
name: 'C',
goods: [{
name: "goods_c1"
}, {
name: "goods_c2"
}, {
name: "goods_c3"
}],
gift: [{
name: "gift_c1",
}]
}]
}
})
HTML:
<div id="app">
<div class="mui-row" v-for="item in list">
<div class="span-title-main">
<span class="span-title">{{item.name}}</span>
</div>
<br>
<ul>
<li>
<div class="mui-col" v-for="items in item.goods">
<span class="span-name">{{items.name}}</span>
</div>
<div class="addspan">+</div>
<div class="mui-col" v-for="itemss in item.gift">
<span class="span-name">{{itemss.name}}</span>
</div>
<div class="addspan">+</div>
</li>
</ul>
</div>
</div>
Are you asking that the (+) being inside the loop of your goods and gift ?
<div id="app">
<div class="mui-row" v-for="item in list">
<div class="span-title-main">
<span class="span-title">{{item.name}}</span>
</div>
<br>
<ul>
<li>
<div class="mui-col" v-for="items in item.goods">
<span class="span-name">{{items.name}}</span>
<div class="addspan">+</div>
</div>
<div class="mui-col" v-for="itemss in item.gift">
<span class="span-name">{{itemss.name}}</span>
</div>
</li>
</ul>
</div>
</div>
Edit: Remove the (+) for gifts loop as requested by OP.
Note: if the OP is asking to have a style for element in between goods and gift. I would suggest to use the css :last selector with a display:none to have this kind of effect.
It looks like the only difference is that you want a + button to appear after each item.goods instead of just one after the loop.
So put it inside the loop:
<template v-for="items in item.goods"><!-- using "template" to avoid modifying your html structure; you could of course use any tag -->
<div class="mui-col">
<span class="span-name">{{items.name}}</span>
</div>
<div class="addspan">+</div>
</template>
<div class="mui-col" v-for="items in item.gift">
<span class="span-name">{{items.name}}</span>
</div>
<!-- your image doesn't show a + button after gifts, so I've omitted it here -->

AngularJS ng-repeat understanding how to find checkbox values

First off new to Angular here :)
I have a page that shows a list of items from a JSON object. That Json object has an array in it of dates
$obj = [
{
id: '1',
GoalName: 'Smoke Less',
StartDate: '9/1/2015',
EndDate: '9/30/2015',
GoalType: "positive",
Category: "Health",
Weight: "3",
TimesPerWeek: 4,
Dates: {
"09/11/2015": 0,
"09/10/2015": 1,
"09/08/2015": 1
}
}
I got ng-repeat to show off the items the array, but I am struggling to understand how to control the checkboxes. When I present the items I set a date on the screen and I want to check the array to see if that date is present and if it is then check the checkbox. And additionally if the user then clicks the checkbox it updates the item. I vaguely understand that I need to make a model of the checkboxes, but don't fully understand how that works.
app.controller('TrackGoals', function ($scope) {
$scope.today = Date.today();
});
<ul class="list" id="thehabits" ng-repeat="goal in goals">
<li class="expanded-cell">
<div class="pull-right form-group cell-content">
<label>
<input type="checkbox" class="option-input checkbox" ng-model="ids[goal.dates.id].value">
</label>
</div>
<div class="cell-content">
<span id="habittext" class="title">{{ goal.GoalName }} </span>
</div>
</li>
</ul>
Try this:
var app = angular.module('myApp', []);
app.controller('TrackGoals', function($scope) {
$scope.goals = [{
id: '1',
GoalName: 'Smoke Less',
StartDate: '9/1/2015',
EndDate: '9/30/2015',
GoalType: "positive",
Category: "Health",
Weight: "3",
TimesPerWeek: 4,
Dates: {
"09/11/2015": 0,
"09/10/2015": 1,
"09/08/2015": 1
}
}, {
id: '2',
GoalName: 'Smoke Less',
StartDate: '9/1/2015',
EndDate: '9/30/2015',
GoalType: "positive",
Category: "Health",
Weight: "3",
TimesPerWeek: 4,
Dates: {}
}];
$scope.setCheckboxVal = function(val) {
var arr = [];
for (var i in val) {
if (val.hasOwnProperty(i)) {
arr.push({
date: i,
value: val[i]
});
}
}
return !!arr.length;
};
$scope.showData = function() {
console.log(JSON.stringify($scope.goals));
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"></script>
<!DOCTYPE html>
<html ng-app='myApp'>
<head>
<meta charset="UTF-8">
<title>Test</title>
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="angular.min.js"></script>
</head>
<body ng-controller="TrackGoals">
<ul class="list" id="thehabits" ng-repeat="goal in goals">
<li class="expanded-cell">
<div class="pull-right form-group cell-content">
<label>
<input type="checkbox" class="option-input checkbox" ng-model="goal.checkboxVal" ng-init="goal.checkboxVal=setCheckboxVal(goal.Dates)">
</label>
</div>
<div class="cell-content">
<span id="habittext" class="title">{{ goal.GoalName }} </span>
</div>
</li>
</ul>
<button type="button" ng-click="showData()">Show data</button>
</body>
</html>

Categories

Resources