Create ul lists dynamically from one array - html

I am working with angularjs (version 1), I know it's old, but I need to work with this version.
I have this list
products = [
{
"productID": 1,
"productName": "product1",
"productCategoryName": "category1"
},
{
"productID": 2,
"productName": "product2",
"productCategoryName": "category1"
},
{
"productID": 3,
"productName": "product3",
"productCategoryName": "category1"
},
{
"productID": 4,
"productName": "product4",
"productCategoryName": "category2"
},
{
"productID": 5,
"productName": "product5",
"productCategoryName": "category2"
},
{
"productID": 6,
"productName": "product6",
"productCategoryName": "category3"
}];
My html code (it's incorrect):
<div class="form-group">
<div ng-repeat="product in vm.products | groupBy: 'productCategoryName'">
{{ product.productCategoryName}}
<ul>
<li>
<input type="checkbox" class="form-check-input" name="something">
<label> {{ product.productName }}</label>
</li>
</ul>
</div>
</div>
The result I want is to be able to create a ul for every productCategoryName, something like this:
<h3>category1</h3>
<ul>
<li>product1</li>
<li>product2</li>
<li>product3</li>
</ul>
<h3>category2</h3>
<ul>
<li>product4</li>
<li>product5</li>
</ul>
<h3>category3</h3>
<ul>
<li>product6</li>
</ul>
I can check if this is true:
<ul ng-if="vm.products[$index - 1].productCategoryName !== product.productCategoryName ">
So I can create a new list when the current index has different category, but my problem here is that I cannot control the closing of the list
I am not sure how can I fix this, would be great if you an help. Thanks!

This is one way of doing it.
<html>
<body ng-app="myapp" ng-controller="mycontroller">
<div class="form-group">
<div ng-repeat="productGroup in groups">
<div>
{{ productGroup.productCategoryName}}
</div>
<ul>
<li ng-repeat="(key, value) in productGroup">
<input type="checkbox" class="form-check-input" name="something">
<label> {{ value.productName }}</label>
</li>
</ul>
</div>
</div>
</body>
</html>
angular.module('myapp', []).controller('mycontroller', function($scope, $filter){
$scope.products = [
{
"productID": 1,
"productName": "product1",
"productCategoryName": "category1"
},
{
"productID": 2,
"productName": "product2",
"productCategoryName": "category1"
},
{
"productID": 3,
"productName": "product3",
"productCategoryName": "category1"
},
{
"productID": 4,
"productName": "product4",
"productCategoryName": "category2"
},
{
"productID": 5,
"productName": "product5",
"productCategoryName": "category2"
},
{
"productID": 6,
"productName": "product6",
"productCategoryName": "category3"
}];
$scope.groups = $filter('groupBy')($scope.products, 'productCategoryName');
})
.filter("groupBy",["$parse","$filter",function($parse,$filter){
return function(array, groupByField){
var result = {};
var prev_item = null;
var groupKey = false;
var filteredData = $filter('orderBy')(array, groupByField);
for(var i=0; i < filteredData.length; i++) {
if (!result[filteredData[i][groupByField]]) {
result[filteredData[i][groupByField]] = [];
result[filteredData[i][groupByField]].productCategoryName = filteredData[i][groupByField];
}
result[filteredData[i][groupByField]].push(filteredData[i]);
}
return result;
}
}])
https://jsfiddle.net/8hscydq9/1/
To help with performance, you can create the group ahead of time and then display that group. Otherwise, on every angular digest it will be recreating the group.

Related

V-If inside V-for, inside V-for

I am a newbie with Vue and I am trying to run an IF statement inside two v-fors.
Basically I am trying to compare a value from one array of objects to a value of another array of objects and if true, render value from array of objects No 2.
Here is the code.
<div v-bind:class="[isActive ? 'projectsWorkingOnActive' : 'projectsWorkingOnInactive']" v-for="rec in listOfEmployees" v-bind:key="rec.id" >
<div v-for="proj in dummyProjectsData" v-bind:key="proj.id">
<div v-if="rec.name.display_value == proj.task_owner">
<h3>Projects Working On</h3>
<ul>
<li>{{proj.projects_working_on.project_name}}</li>
<li><submitbutton button_label="Hide Projects" #click="toggleClass()"></submitbutton></li>
</ul>
</div>
</div>
</div>
And here are my 2 arrays of objects.
const dummyProjectsData = [
{
ID: "44000005501077",
task_owner: "Denis Denchev",
projects_working_on: [
{
"project_name": "Project-1",
"project_id": "195000002362044"
},
{
"project_name": "Project-2",
"project_id": "195000002362045"
},
{
"project_name": "Project-3",
"project_id": "195000002362046"
},
]
},
{
ID: "44000005501078",
task_owner: "Jake Jones",
projects_working_on: [
{
"project_name": "Project-2",
"project_id": "195000002362044"
},
{
"project_name": "Project-5",
"project_id": "195000002362045"
},
{
"project_name": "Project-3",
"project_id": "195000002362046"
},
]
},
]
And the second array...
const listOfEmployees = [
{
"ID": "44000005527013",
"name": {
"display_value": "Denis Denchev",
"first_name": "Denis",
"last_name": "Denchev",
"prefix": "",
"suffix": "",
}
}
]
What am I doing wrong? It must be something silly that I am missing? Or can I not do if statement taking value from two v-for's ?
The problem is that proj.projects_working_on is an array of multiple projects, but you are trying to access a property on it like an object. Change to something like:
<div v-bind:class="[isActive ? 'projectsWorkingOnActive' : 'projectsWorkingOnInactive']" v-for="rec in listOfEmployees" v-bind:key="rec.id" >
<div v-for="proj in dummyProjectsData" v-bind:key="proj.id">
<div v-if="rec.name.display_value == proj.task_owner">
<h3>Projects Working On</h3>
<ul>
<li v-for="p in proj.projects_working_on" v-bind:key="p.project_id">
{{ p.project_name }}
</li>
<li><submitbutton button_label="Hide Projects" #click="toggleClass()"></submitbutton></li>
</ul>
</div>
</div>
</div>

AngularJS Images from JSON file would not load using ng-src how to display image

I am using AngularJS to read image data from a JSON file, which works for other data except images.
ng-src is not fetching any image?
I need to load all the images to the div and populate the src, alt, and title attributes of the image data I read in using ng-repeat, however it does not work. What happen?
Then, I am not sure the way the code is setup works?
These are my code-
<!DOCTYPE html>
<html ng-app="store">
<head>
<link rel="stylesheet" type="text/css" href="bootstrap.min.css">
</head>
<body ng-controller = "storeController">
<script type="text/javascript" src="angular.min.js"></script>
<script type="text/javascript" src="app.js"></script>
<!--<button class="btn btn-primary" ng-click="showMessage = !showMessage">Toggle Message</button>
<h2 ng-show="showMessage == true">Secret Message</h2>
<input type="text" placeholder="Leave a Message" ng-model="message">
<h2>{{ message }}</h2>-->
<div class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">ngPlaces</a>
</div>
</div>
</div>
<div class="container">
<div class="col-sm-4" ng-repeat = "place in places">
<div class="thumbnail">
<img ng-src="images/{{cribs.image}}.jpg" alt="">
<div class="caption">
<h3>{{place.address}}</h3>
<p><strong>Type:</strong>{{place.type}}</p>
<p><strong>Description:</strong>{{place.description}}</p>
<p><strong>Price:</strong>{{place.price | currency}}</p>
</div>
</div>
</div>
</div>
</body>
</html>
my json data
[
{
"id": 1,
"type": "Condo",
"price": 220000,
"address": "213 Grove Street",
"description": "Excellent place, really nice view!",
"details": {
"bedrooms": 2,
"bathrooms": 1.5,
"area": 921
},
"image":"crib-1"
},
{
"id": 2,
"type": "House",
"price": 410500,
"address": "7823 Winding Way",
"description": "Beautiful home with lots of space for a large family.",
"details": {
"bedrooms": 4,
"bathrooms": 3,
"area": 2145
},
"image":"crib-2"
},
{
"id": 3,
"type": "Duplex",
"price": 395000,
"address": "834 River Lane",
"description": "Great neighbourhood and lot's of nice green space.",
"details": {
"bedrooms": 3,
"bathrooms": 2.5,
"area": 1500
},
"image":"crib-3"
},
{
"id": 4,
"type": "House",
"price": 755990,
"address": "7807 Forest Avenue",
"description": "Best house on the block!",
"details": {
"bedrooms": 6,
"bathrooms": 4.5,
"area": 3230
},
"image":"crib-4"
},
{
"id": 5,
"type": "Condo",
"price": 210500,
"address": "1857 Andover Court",
"description": "Nice little condo with room to grow.",
"details": {
"bedrooms": 2,
"bathrooms": 1.5,
"area": 1023
},
"image":"crib-5"
},
{
"id": 6,
"type": "House",
"price": 334900,
"address": "7398 East Avenue",
"description": "You'll love the view!",
"details": {
"bedrooms": 4,
"bathrooms": 2.5,
"area": 1788
},
"image":"crib-6"
}
]
app.js
(function(){
var app = angular.module('store', []);
app.controller('storeController', function($scope, placesFactory){
$scope.places;
placesFactory.getPlaces().then(function(response){
$scope.places = response.data;
});
$scope.sayHello = function(){
console.log("Hello");
}
});
app.factory('placesFactory', function($http){
function getPlaces(){
return $http.get('data.json');
}
return {
getPlaces: getPlaces
}
});
})();
Change
From
<img ng-src="images/{{cribs.image}}.jpg" alt="">
To
<img ng-src="images/{{place.image}}.jpg" alt="">

key value in ng-repeat and large JSON

I have jsons like this one:
JSON "myWelcome"
[
{"BACKGROUND": {
"BACK": {
"NAME": "asd"},
"AGE": "13",
"YEAR": "2016"
}},
{"NAILS": {
"BACK": {
"NAME": "asd"},
"AGE": {
"AG": "14"},
"YEAR": "2014",
"CENT": "dsds"
}}
]
What i need to do is show everything from this json in <ul> or table, but not by name. My HTML:
<ul ng-repeat="(key, value) in myWelcome">
<ul ng-repeat="val in value">
<ul ng-repeat="(o, values) in val">
<li>{{o}}</li><li>{{values}}</li>
</ul>
</ul>
</ul>
It not quite work because "NAME" in "BACK" shows all.
Thanks for answers in advance.
You can use this code to make it work, but it will only work on this data sample or a similar one, any changes in the JSON might break it also.
<ul ng-repeat="(key, value) in myWelcome">
<ul ng-repeat="val in value">
<ul ng-repeat="(o, values) in val">
<li>{{o}}</li><li ng-if="key=='NAILS'&& o=='AGE'" >{{values.ag}}</li><li ng-if="!key=='NAILS'&& o=='AGE'">{{values}}</li>
</ul>
</ul>
</ul>
You can first remove all the properties having key as NAME recursively then iterate using ng-repeat.
DEMO
var jsonObj = [
{"BACKGROUND": {
"BACK": {
"NAME": "asd"},
"AGE": "13",
"YEAR": "2016"
}},
{"NAILS": {
"BACK": {
"NAME": "asd"},
"AGE": {
"AG": "14"},
"YEAR": "2014",
"CENT": "dsds"
}}
];
function removeMeta(obj) {
for(prop in obj) {
if (prop === 'NAME')
delete obj[prop];
else if (typeof obj[prop] === 'object')
removeMeta(obj[prop]);
}
};
removeMeta(jsonObj);
console.log(jsonObj);

Vue - input with multiple checkboxes

I'm rendering some checkboxes based on an array and using a data attribute as the v-model. I'm using Vue2.
However, I end up having all checkboxes checked for some reason, when the value of the v-model equals 1 (I guess it treats it as a bool instead of a number).
I tried v-model.number - without any luck. What am I doing wrong?
My template:
<div v-for="category in categories">
<input
type="checkbox"
v-model.number="item.category"
:id="'category_' + category.id"
:value="category.id"
#change="save"
/>
<label>{{ item.category }} : {{ category.id }}</label>
</div>
Model Data (item.category):
1
Categories:
[
{
"id": 2,
"name": "news Category 0"
},
{
"id": 7,
"name": "news Category 1"
},
{
"id": 12,
"name": "news Category 2"
},
{
"id": 17,
"name": "news Category 3"
},
{
"id": 22,
"name": "news Category 4"
},
{
"id": 27,
"name": "news Category 5"
},
// other values
]
Screenshot (Ive added item.category and category.id as label text to make it more clear):
As you are using Multiple checkboxes, you have to give an array in v-model, so your item.category has to be an array: [1].
See the working fiddle: https://jsfiddle.net/mimani/y36f3cbm/
var demo = new Vue({
el: '#demo',
data() {
return {
categories: [{
"id": 2,
"name": "news Category 0"
}, {
"id": 92,
"name": "news Category 8"
}, {
"id": 97,
"name": "news Category 9"
}],
item: {
category: [1]
}
};
}
})

Nested JSON in one ng-repeat

I'm somewhat new to angular, and i'm having problems with ng-repeats. I have one ng-repeat that have to show nested objects in each repeat. You know what I mean?
This is the HTML:
<li ng-repeat="rm in rooms">
<a href="">
<span id="room">{{rm.room}}</span>
<span id="rack_num">Rack {{rm.rack}}</span>
<span id="slot_type">{{rm.type}}</span>
<span id="slot_id">Slot {{rm.id}}</span>
</a>
</li>
I have a list of "rooms" and "racks" and "slots":
[
{
"room": 1,
"rackroom": [
{
"rack": 8,
"rackslots": [
{
"slot": 1,
"id": "EZ345T1R",
"type": "single"
}
]
},
{
"rack": 12,
"rackslots": [
{
"slot": 3,
"id": "56XZU28",
"type": "double"
}
]
}
]
},
{
"room": 2,
"rackroom": [
{
"rack": 12,
"rackslots": [
{
"slot": 1,
"id": "TZE57DG",
"type": "single"
}
]
},
{
"rack": 32,
"rackslots": [
{
"slot": 7,
"id": "778GHRT",
"type": "double"
}
]
}
]
}
]
My controller looks like this:
$http.get('data/data.json').success(function(data) {
$scope.rooms = [];
$scope.slots = [];
$scope.racks = [];
angular.forEach(data, function(key, val){
$scope.rooms.push(key);
angular.forEach(key.rackroom, function(key, val){
$scope.racks.push(key);
angular.forEach(key.rackslots, function(key, val){
$scope.slots.push(key);
});
});
});
});
The output should look something like this:
• Room: 1
• Rack: 12
• Type: single
• Slot: 3
• Room: 1
• Rack: 24
• Type: single
• Slot: 8
It seems like I'm wrong because just the rooms appear but not the nested objects. If I make 3 separate repeats (slot in slots, rack in racks, room in rooms) they all appeear, but I need it all in one repeat ...
Thank you for Help!
You basically need to flatten your nested data:
$http.get('data/data.json').success(function(data) {
$scope.rooms = [];
for (var i = 0; i < data.length; i++) {
var room = data[i];
for (var j = 0; j < room.rackroom.length; j++) {
var rack = room.rackroom[j];
for (var k = 0; k < rack.rackslots.length; k++) {
var slot = rack.rackslots[k];
$scope.rooms.push({
room: room.room,
rack: rack.rack,
slot: slot.slot,
type: slot.type
});
}
}
}
});
<li ng-repeat="rm in rooms">
<a href="">
<span id="room">{{rm.room}}</span>
<span id="rack_num">Rack {{rm.rack}}</span>
<span id="slot_type">{{rm.type}}</span>
<span id="slot_id">Slot {{rm.slot}}</span>
</a>
</li>
I think the following is very close to what you want:
var app = angular.module('demo', []);
app.controller('MainCtrl', function($scope) {
var data = [{
"room": 1,
"rackroom": [{
"rack": 8,
"rackslots": [{
"slot": 1,
"id": "EZ345T1R",
"type": "single"
}]
}, {
"rack": 12,
"rackslots": [{
"slot": 3,
"id": "56XZU28",
"type": "double"
}]
}]
}, {
"room": 2,
"rackroom": [{
"rack": 12,
"rackslots": [{
"slot": 1,
"id": "TZE57DG",
"type": "single"
}]
}, {
"rack": 32,
"rackslots": [{
"slot": 7,
"id": "778GHRT",
"type": "double"
}]
}]
}];
$scope.rooms = [];
angular.forEach(data, function(room) {
angular.forEach(room.rackroom, function(rack) {
angular.forEach(rack.rackslots, function(slot) {
$scope.rooms.push({
room: room.room,
rack: rack.rack,
type: slot.type,
slot: slot.slot
});
});
});
});
});
.room,
.rack_num,
.slot_type,
.slot_id {
display: list-item;
}
.room_item {
margin: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<div ng-app="demo" ng-controller="MainCtrl">
<ul>
<li class="room_item" ng-repeat="rm in rooms">
<a href="">
<span class="room">Room: {{rm.room}}</span>
<span class="rack_num">Rack: {{rm.rack}}</span>
<span class="slot_type">Type: {{rm.type}}</span>
<span class="slot_id">Slot {{rm.slot}}</span>
</a>
</li>
</ul>
</div>
The markup may not quite be right, but you can tweak it from here.
Also, if you are going to repeat something, you shouldn't use id for those elements. ids are supposed to be unique across the whole page. Use classes instead, like I did.