AngularJS ng-repeat understanding how to find checkbox values - javascript

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>

Related

How do I remove the limit of a limitTo filter on mouseover event?

I have an array of objects called articles each of which contains an array of strings called category. Each article is represented in the DOM with an ngRepeat directive which contains a second ngRepeat directive to represent each category. The second ngRepeat has a limitTo filter that limits the number of categories to 2. When the user mouses over the base article element the limit should be removed and all strings in the category array should be visible.
My problem is that when a user mouses over one element the full array of categories for every object in the articles array is revealed. How can I get the DOM to reveal only the full categories for the element the mouse event takes place on?
Plunkr: https://plnkr.co/edit/PW51BBnQEv589rIdnaCK?p=preview
You can pass your article on which you hover and set in a scope variable. Than simply update your ng-if check to :
ng-if="hoverMode === true && hoveredArticle === article"
Working example :
// Code goes here
angular
.module('myApp', [])
.controller('myController', ($scope) => {
$scope.articles = [ { date: 'some', category: [ {name: "Sports"}, {name: "News"}, {name: "Cinema"} ] }, { date: 'some', category: [ {name: "A"}, {name: "B"}, {name: "C"} ] }, { date: 'some', category: [ {name: "D"}, {name: "E"}, {name: "F"} ] } ]
$scope.hoverMode = false;
$scope.showAllcat = function(article) {
$scope.hoveredArticle = article;
$scope.hoverMode = true;
}
$scope.hideAllcat = function() {
$scope.hoveredArticle = null;
console.log('hover working');
$scope.hoverMode = false;
}
});
<!DOCTYPE html>
<html ng-app='myApp'>
<head>
<script data-require="angular.js#4.0.0" data-semver="4.0.0" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.10/angular.min.js"></script>
<script data-require="angular.js#4.0.0" data-semver="4.0.0" src="script.ts"></script>
<script data-require="angular.js#4.0.0" data-semver="4.0.0" src="system.config.js"></script>
<script data-require="angular.js#4.0.0" data-semver="4.0.0" src="tsconfig.json"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller='myController'>
<table>
<tbody>
<tr>
<th>Date</th>
<th>Categories</th>
</tr>
<tr ng-repeat="article in articles">
<td><span>{{ article.date }}</span></td>
<td ng-if="hoverMode === false || hoveredArticle !== article">
<span ng-repeat="cat in article.category | limitTo: 2">
<span class="label label-warning"
ng-mouseover="showAllcat(article)">{{ cat.name}}
</span>
</span>
</td>
<td ng-if="hoverMode === true && hoveredArticle === article">
<span ng-repeat="cat in article.category">
<span class="label label-warning"
ng-mouseleave="hideAllcat()">{{ cat.name}}
</span>
</span>
</td>
</tr>
</tbody>
</table>
</body>
</html>
Here's another way this can be approached. I removed the ng-if directive as it is not needed. In your first ng-repeat directive the article object is available in the scope to be used. $scope.hoverMode was removed in favor of adding an attr to each article called limit.
The ng-mouseover event i replaced in favor of ng-mouseenter as it is the parallel event to ng-mouseleave. Instead of having these directives call a function, the limit value is manipulated via a simple expression in the DOM.
I left the function showAllCat() in the code with modifications. It takes an article object as a parameter to manipulate the category directly.
If the limit var is undefined, then there is no limit constraint in the filter.
By removing ng-if you're removing n number of listeners equivalent to the number of articles. Since it wasn't needed, that's just extra overhead.
// Code goes here
angular
.module('myApp', [])
.controller('myController', ($scope) => {
$scope.minLimit = 2;
$scope.maxLimit = undefined;
$scope.articles = [{
date: 'some',
category: [{
name: "Sports"
}, {
name: "News"
}, {
name: "Cinema"
}]
}, {
date: 'some',
category: [{
name: "A"
}, {
name: "B"
}, {
name: "C"
}]
}, {
date: 'some',
category: [{
name: "D"
}, {
name: "E"
}, {
name: "F"
}]
}];
$scope.articles.forEach((article)=>{article.limit=$scope.minLimit});
$scope.showAllcat = function(article) {
console.log('hover working');
article.limit = article.limit === minLimit ? maxLimit : minLimit;
}
});
<!DOCTYPE html>
<html ng-app='myApp'>
<head>
<script data-require="angular.js#4.0.0" data-semver="4.0.0" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.10/angular.min.js"></script>
<script data-require="angular.js#4.0.0" data-semver="4.0.0" src="script.ts"></script>
<script data-require="angular.js#4.0.0" data-semver="4.0.0" src="system.config.js"></script>
<script data-require="angular.js#4.0.0" data-semver="4.0.0" src="tsconfig.json"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller='myController'>
<table>
<tbody>
<tr>
<th>Date</th>
<th>Categories</th>
</tr>
<tr ng-repeat="article in articles"
ng-mouseenter="article.limit = maxLimit"
ng-mouseleave="article.limit = minLimit">
<td><span>{{ article.date }}</span></td>
<td><span ng-repeat="cat in article.category | limitTo: article.limit">
<span class="label label-warning">{{cat.name}}
</span>
</span>
</td>
</tr>
</tbody>
</table>
</body>
</html>

Using V-model on a loop

I am trying to use v-model on v-for loop and its throwing an error.
How can i get this to work
<ul class="">
<li class="" v-model="category.data" v-for="category in categories" :key="category.id">
<input :id="'checkbox'+ category.id" type="checkbox" #change="categoriesComputed($event)" :value="category.slug">
<label :for="'checkbox'+ category.id">
{{category.title | capitalize}}
<span>{{category.job_posts | countObj | toNumber}} Jobs</span>
</label>
</li>
</ul>
And in Vue
<script>
export default {
data(){
return {
type: [],
categories: [],
category: {
data: [],
},
}
},
}
</script>
V-model only works if it’s being used on an input element or a custom component that emits a value event that supplies the value you want v-model to be updated with.
https://v2.vuejs.org/v2/guide/forms.html
https://jsfiddle.net/amcquistan/grq3qj36/
V-model is demo in this fiddle
You have to use v-model in the <input> tags.
const app = new Vue({
el: '#app',
data: {
categories: [
{ id: 1, slug: true, title: 'FOO', job_posts: 'Foo'},
{ id: 2, slug: false, title: 'BAR', job_posts: 'Bar'},
{ id: 3, slug: true, title: 'BAZ', job_posts: 'Baz'}
]
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app">
<ul class="">
<li class="" v-for="category in categories" :key="category.id">
<input
:id="'checkbox'+ category.id"
type="checkbox"
v-model="category.slug">
<label :for="'checkbox'+ category.id">
{{category.title}} {{category.slug}}
</label>
<input v-model="category.title"/>
</li>
</ul>
</div>

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 -->

ng-repeat updates all the form

I'm trying to do kind of a cart in IONIC ( I'm new using this framework as well ).
I have a ng-repeat to fill my screen with products from the database (firebase), inside this ng-repeat I have a form.
My form contais 3 elements, an an and a button. When I fill my form and press add. it works fine. but if I add a second product, my first one gets updated with the value of the new one. Exemple:
1) Add a product A. Qtd: 3 unity: mg.
2) Add a product B. Qtd: 8 utity: g.
Then my first product turn into: product A. Qtd: 8 unity: m8.
Some one can please help me?
Following my HTML and my JS
$scope.category = Category.name;
$scope.amount = {count: '', unit: 'mg'};
function AddToCart(product, amount)
{
if(amount.count == null)
return;
if(!$rootScope.cart)
$rootScope.cart = [];
$rootScope.cart.push({
item: product,
qtd: amount
});
showToast();
}
<div class="item item-product" id="{{$index}}-item" ng-repeat="item in vm.Products | filter:filter.product" >
<p style="width: 95%; margin: 0;">{{item.name}}</p>
<button class="arrow-button" ng-click="showDetails($index)" sytle = "border: none; width: 100%;"><i class="icon ion-ios-arrow-right"></i></button>
<div class="details" id ="{{$index}}-details" style="z-index: 999;">
<hr>
<p> {{item.about}}</p>
<form class="cart-area" id ="{{$index}}-form" ng-submit="vm.AddToCart(item, amount,$index)">
<input type="number" id = "{{$index}}-input" ng-model="amount.count" placeholder="Qtd">
<div class="list">
<select ng-model="amount.unit">
<option>mg</option>
<option selected>g</option>
<option>kg</option>
</select>
</div>
<button><i class="fa fa-plus" aria-hidden="true"></i>Adicionar cotação</button>
</form>
</div>
</div>
Okay, so you were on the right track, but didn't quite understand how to bind the controls to a specific product - you were binding them to a shared scope, which is why when you updated one, you updated all of them. That is the nature of the two-way data binding built in to AngularJS.
What you want to do is bind the ng-model value to a property on the item itself, like so:
var app = angular.module("myApp", [])
.controller("myCtrl", ["$scope",
function($scope) {
var $this = this;
$this.Products = [{
name: "Product 1",
about: "Info About Product 1",
count: 3,
unit: "mg"
}, {
name: "Product 2",
about: "Info About Product 2",
count: 8,
unit: "g"
}, {
name: "Product 3",
about: "Info About Product 3",
count: 2,
unit: "kg"
}, ];
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl as vm">
<h3>Solution using properties on Products</h3>
<div class="item item-product" id="{{$index}}-item" ng-repeat="item in vm.Products | filter:filter.product">
<p style="width: 95%; margin: 0;">{{item.name}}</p>
<div class="details" id="{{$index}}-details" style="z-index: 999;">
<hr>
<p>{{item.about}}</p>
<div ng-form="{{$index}}-form" class="cart-area" ng-submit="vm.AddToCart(item, amount,$index)">
<input type="number" ng-model="item.count" placeholder="Qtd">
<div class="list">
<select ng-model="item.unit">
<option value="mg">mg</option>
<option value="g">g</option>
<option value="kg">kg</option>
</select>
</div>
<button><i class="fa fa-plus" aria-hidden="true"></i>Adicionar cotação</button>
</div>
</div>
</div>
</div>

Displaying a grid of images sorted by category using angularjs

I am building a web application using angular and I want to display a grid of items sorted by category. Each row will correspond to a certain category. This is what my code looks like:
<ion-item ng-repeat="item in items|filter:query|orderBy:'name' ">
<div class="row" ng-scrollable style="width:400px;height:300px;">
<div class="col">
<img ng-src={{item.img}}/>
<p>{{item.name}}</p>
<p>Old Price: {{item.newPrice}}</p>
<p>New Price: {{item.newPrice}}</p>
<button class ="button" ng-click="addToGrocery()">Add to List</button>
</div>
</div>
My controller.js file looks like this:
.controller('CouponsCtrl', function($scope) {
$scope.items = [{ name: 'Banana', newPrice: 3.29, oldPrice: 4.49, aisle: 'A', img: 'http://placehold.it/280x150', category: 'Fruits' },
{ name: 'Chocolate', newPrice: 3.19, oldPrice: 5.39, aisle: 'B', img: 'http://placehold.it/280x150' , category: 'Dairy'},
{ name: 'Brocolli', newPrice: 2.29, oldPrice: 4.40, aisle: 'D', img: 'http://placehold.it/280x150' , category: 'Vegetables'}
];
})
I believe I need nested ng-repeats but I am not sure how to incorporate that.
Base on groupby Group item detail using AngularJs ng-repeat
<body ng-controller="con">
<div ng-repeat="(setKey, set) in items|filter:query|orderBy:'name'|groupBy:'category'">
{{setKey}}
<div ng-repeat="item in set">
<div class="row" ng-scrollable="" style="width:400px;height:300px;">
<div class="col">
<img ng-src="{{item.img}}/" />
<p>{{item.name}}</p>
<p>Old Price: {{item.newPrice}}</p>
<p>New Price: {{item.newPrice}}</p>
<button class="button" ng-click="addToGrocery()">Add to List</button>
</div>
</div>
</div>
</div>
</body>
http://plnkr.co/edit/GMW52iJyRlQ2otZndGLM?p=preview

Categories

Resources