Collapse/Expand nested div in Angular 6 - html

I am developing a schedule like structure using div. And my design looks like this.
What i want is when loading, only 1st level should be displayed (all venues) and when clicking on venue its immediate child should be displayed and so on. Is there any way to do so. my html is:
<div class="div-table">
<div class="div-table-row">
<div class="div-header-col" style="visibility: hidden;">A</div>
<div *ngFor="let date of dates" class="div-date-col">{{date | date:'d E'}}</div>
</div>
<!-- level1 -->
<div *ngFor="let venue of venues" class="level1" style="color: red">
<div class="div-table-row-level1" >
<div class="div-header-col">{{venue.name}}</div>
<div *ngFor="let x of dates" class="div-event-level1-col"></div>
</div>
<!-- level2 -->
<div *ngFor="let category of venue.categories" class="level2" style="color: blue">
<div class="div-table-row-level2">
<div class="div-header-col" style="padding-left: 10px">{{category.name}}</div>
<div *ngFor="let x of dates" class="div-event-level2-col"></div>
</div>
<!-- level3 -->
<div *ngFor="let asset of category.assets" class="level3" style="color: green">
<div class="div-table-row-level3">
<div class="div-header-col" style="padding-left: 20px">{{asset.name}}</div>
<div *ngFor="let x of dates" class="div-event-level3-col assest-hover" "></div>
</div>
</div>
</div>
</div>
</div>
My data for the table(div) is :
[
{
"id":1,
"name":"venue1",
"categories":[
{
"id":1,
"name":"cat1",
"assets":[
{
"id":1,
"name":"assest1"
},
{
"id":2,
"name":"assest2"
}
]
},
{
"id":2,
"name":"cat2",
"assets":[
{
"id":3,
"name":"assest3"
},
{
"id":4,
"name":"assest4"
}
]
}
]
},
{
"id":2,
"name":"venue2",
"categories":[
{
"id":3,
"name":"cat3",
"assets":[
{
"id":5,
"name":"assest5"
},
{
"id":6,
"name":"assest6"
}
]
},
{
"id":4,
"name":"cat4",
"assets":[
{
"id":7,
"name":"assest7"
},
{
"id":8,
"name":"assest8"
}
]
}
]
},{
"id":3,
"name":"venue3",
"categories":[
{
"id":5,
"name":"cat5",
"assets":[
{
"id":9,
"name":"assest9"
},
{
"id":10,
"name":"assest10"
}
]
},
{
"id":6,
"name":"cat6",
"assets":[
{
"id":11,
"name":"assest11"
},
{
"id":12,
"name":"assest12"
}
]
}
]
}
]

If you have entire data loaded together then you have good news that it can be implemented in a very simple way -
You can play around Element Reference. Nothing needs to be managed from ts file.
in html
<div *ngFor="let venue of venues" class="level1" style="color: red"
(click)="ele.class = ele.class == 'showChildren' ? '' : 'showChildren'"
[ngClass]="{ hideChildren : ele.class !== 'showChildren' }">
Repeat the same for all parent div
in CSS
.hideChildren>div{
display: none;
}
Here is the working copy- https://stackblitz.com/edit/angular-n43ihd
There are some more way to handle if the data is being fetched in Asynchronous fashion. Then these logic will move to ts file.

You can try to hide component's on-load, and set them to visible onClick
$scope.$on('$viewContentLoaded', function() {
// Hide all unwanted div's here
});

Related

AngularJS nested objects in the same bootstrap row

i have a JSON object
{
"products": [
{
"devices": [
{
"label": "P1D1"
},
{
"label": "P1D2"
}
]
},
{
"devices": [
{
"label": "P2D1"
},
{
"label": "P2D2"
}
]
}
]
}
and i want to have in HTML something like this
<div class="row">
<div class="col-3">
P1D1
</div>
<div class="col-3">
P1D2
</div>
<div class="col-3">
P2D1
</div>
<div class="col-3">
P2D2
</div>
</div>
AngularJS is the language i am using, but i don't seem the find the right syntax
<div class="row">
<div ng-repeat="product in obj.products">
<div class="col-3" ng-repeat="device in product.devices">
{{device.label}}
</div>
</div>
</div>
How can i achieve all the subitems to be displayed in a bootstrap column next to eachother?
I think you can't do it directly using only HTML. Alternatively you can use some manipulation in Javascript to flatten your data.
JAVASCRIPT
$scope.getItems = function(){
return $scope.obj.products.flatMap(function(element){
return element.devices;
})
}
HTML
<div class="col-3" ng-repeat="device in getItems()">
{{device.label}}
</div>
Check my example:
https://codepen.io/avgustint/pen/XWYyoyd?editors=1111

Nested Children Json in Angular HTML

I have a JSON with nested children. RowElements can have n colElements and colElements can have n RowElements.
JSON
"container": {
"id": "37ec0632-3391-4ef5-a9cb-25db2216fa75",
"rowElements": [
{
"id": "80e1dae7-b497-48d3-80ad-b94d36ada642",
"colElements": [
{
"id": "c662efe9-615c-4de5-97d3-2b02a5bce831",
"rowElements": [
{
"id": "b31960fd-c082-4d3b-88fc-c05f0cf837aa",
"colElements": []
},
{
"id": "7552306a-ca61-4d80-bb4e-d6c8d15c2c78",
"colElements": []
},
{
"id": "f669896d-132b-468e-8dcf-f2b59d509a76",
"colElements": []
}
]
}
]
}
]
}
How can i iterate over the children dynamically in the template like:
<div class="row">
<div class="col">
<div class="row">
<div class="col">
</div>
<div class="col">
</div>
<div class="col">
</div>
...
</div>
...
</div>
...
</div>
You can use nested *ngFor to iterate the JSON and display it dynamically.
I also created a stackblitz for you to check my solution.
HTML - I'm display the id here just to check the JSON.
<div class="row" *ngFor="let firstRow of arr.container.rowElements">
{{ firstRow.id }}
<div class="col" *ngFor="let firstCol of firstRow.colElements">
{{ firstCol.id }}
<div class="row" *ngFor="let secondRow of firstCol.rowElements">
{{ secondRow.id }}
<div class="col" *ngFor="let secondCol of secondRow.colElements"></div>
</div>
</div>
</div>
AppComponent.ts - I added a variable to hold your sample JSON
export class AppComponent {
arr = {
container: {
id: '37ec0632-3391-4ef5-a9cb-25db2216fa75',
rowElements: [{
id: '80e1dae7-b497-48d3-80ad-b94d36ada642',
colElements: [{
id: 'c662efe9-615c-4de5-97d3-2b02a5bce831',
rowElements: [{
id: 'b31960fd-c082-4d3b-88fc-c05f0cf837aa',
colElements: []
},
{
id: '7552306a-ca61-4d80-bb4e-d6c8d15c2c78',
colElements: []
},
{
id: 'f669896d-132b-468e-8dcf-f2b59d509a76',
colElements: []
},
],
}, ],
}, ],
},
};
constructor() {
console.log(this.arr.container);
}
}

Select from JSON, use radio input in Vue.js

I have props: ['attributes']
{
"name": "Color",
"variant": [
{
"name": "Red"
},
{
"name": "Green"
},
{
"name": "Blue"
}
]
},
{
"name": "Size",
"variant": [
{
"name": "L"
},
{
"name": "XL"
},
{
"name": "XXL"
}
]
}
In Template:
<div class="form-group" v-for="(attribute, index) in attributes">
{{attribute.name}}
<div v-for="(variant, vindex) in attribute.variant">
<input type="radio"
:value="[{name: attribute.name, variant:variant.name}]"
:id="'radio' + vindex"
:name="'group' + index">
{{variant.name}}
</div>
</div>
Result:
enter image description here
Question: How do I return selected radio buttons in an array? For example:
[{
"name": "Color",
"variant":
{
"name": "Blue"
}
},
{
"name": "Size",
"variant":
{
"name": "XL"
}
}]
The radio button does not add to the array as a checkbox.
You can do something like this.
You need to splice existing item each time so new value added.
Main part was searching item and removing and you can do it by looping through current items and find index of existing item and remove it so new value can be updated.
check below code.
var attributes = [{
"name": "Color",
"variant": [
{
"name": "Red"
},
{
"name": "Green"
},
{
"name": "Blue"
}
]
},
{
"name": "Size",
"variant": [
{
"name": "L"
},
{
"name": "XL"
},
{
"name": "XXL"
}
]
}];
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!',
attributes: attributes,
selectedData:[]
},
methods:{
setValue( name, value) {
//console.log(name,value);
var self = this;
this.selectedData.forEach(function(val, index){
if(val['name'] == name) {
self.selectedData.splice(index, 1);
return false;
}
});
this.selectedData.push({
"name": name,
"variant":
{
"name": value
}
});
}
}
})
<!DOCTYPE html>
<html>
<head>
<script> console.info = function(){} </script>
<script src="https://vuejs.org/js/vue.js"></script>
<script src="https://code.jquery.com/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<style>.half{width:50%;float:left;}</style>
</head>
<body>
<div id="app">
<div class="half">
<div class="form-group" v-for="(attribute, index) in attributes">
{{attribute.name}}
<div v-for="(variant, vindex) in attribute.variant">
<label>
<input #click="setValue(attribute.name, variant.name)" type="radio"
:value="[{name: attribute.name, variant:variant.name}]"
:id="'radio' + vindex"
:name="'group' + index">
{{variant.name}}</label>
</div>
</div>
</div>
<div class="half">
<pre>{{ selectedData }}</pre></div>
</div>
</body>
</html>

How to set angularjs dropdown option value?

I have succesfully setup the option in both dropdowns.
In my dropdown one is dependent to another
Suppose in my database Parent name is Sally and child name is SallyChild2,when an updating this page, i need to populate the entire data
with select this particular parent name as Sally and childname as SallyChild2
My database value is Parent - Sally and Child - SallyChild2
So i want to change Child - SallyChild1
So I hard coded as this wat but not working
$scope.selectedParent="Sally";
$scope.selectedChild="SallyChild2";
But its not working
This is my script.js
script.js
var app=angular.module('TestApp', ['angular.filter','ui.router']);
app.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('category',
{
views : {
"body" :
{
url : '/category',
templateUrl : 'category.html',
controller : 'TestController'
}
}
})
.state('category.subcategory',
{
url : '/subcategory',
views : {
"subbody#category" :
{
templateUrl : 'sample.html',
controller : 'SampleController'
}
}
})
});
app.controller('MainController', MainController);
function MainController($scope,$state)
{
alert("This is MainController")
$scope.getCategory=function()
{
$state.go('category');
}
}
app.controller('TestController', TestController);
//TestController.$inject['dataservice'];
function TestController($scope, $state){
$scope.data=[
{
"parentName": "George",
"childName": "George Child1"
},
{
"parentName": "Folly",
"childName": "FollyChild1"
},
{
"parentName": "Sally",
"childName": "Sally Child1"
},
{
"parentName": "George",
"childName": "GeorgChild2"
},
{
"parentName": "Folly",
"childName": "FollyChild2"
},
{
"parentName": "Folly",
"childName": "Infant Food"
},
{
"parentName": "Sally",
"childName": "SallyChild2"
}
];
$scope.selectedParent="Sally";
$scope.selectedChild="SallyChild2";
function onParentChange(parent){
if(!parent){
$scope.child = undefined;
}
}
$scope.getValue=function()
{
alert("Call to Sample Controller")
var currentState = $state.current.name;
var targetState = 'category.subcategory';
if(currentState === targetState)
$state.go($state.current, {}, {reload: true});
else
$state.go(targetState);
$state.go(".subcategory");
//$state.go('category.subcategory');
}
}
app.controller('SampleController', SampleController);
function SampleController($scope,$state)
{
alert("This is SampleController")
}
index.html
<!DOCTYPE html>
<html ng-app="TestApp">
<head>
<link rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular-route.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.8/angular-filter.js"></script>
<script src="angular-ui-router.js"></script>
<script src="script.js"></script>
<script src="angular-filter.js"></script>
</head>
<body ng-controller="MainController">
Click to Category
<div ui-view="body"></div>
</body>
</html>
category.html
<div>
<hr>
<div class="col-md-3">
<form>
<div class="form-group">
<label for="exampleSelect1"><b>Parent</b></label>
<select ng-model="selectedParent"
ng-init="selectedParent = null"
ng-change="onParentChange(selectedParent)"
class="form-control" id="data">
<option value="">--Select--</option>
<option ng-repeat="(key,value) in data | orderBy:'parentName'| groupBy:'parentName'">{{key}}</option>
</select>
</div>
</form>
</div>
<div class="col-md-3">
<form>
<div class="form-group">
<label for="exampleSelect1"><b>Child Names</b></label>
<select class="form-control" id="childnames" ng-model="child"
ng-disabled="!selectedParent"
ng-options="data.childName for data in data| filter: {parentName:selectedParent} | removeWith:{childName : 'Infant Food'}" ng-change="getValue()">
<option value="">--Select--</option>
</select>
</div>
</form>
</div>
<div ui-view="subbody"></div>
</div>
sample.html
<div>
Sample Controller
</div>

Multidimensional array with jquery templates

I have the following javascript object
var arr = [
[
{ "id": 1, "name": "one" },
{ "id": 2, "name": "two" },
{ "id": 3, "name": "three" }
],
[
{ "id": 4, "name": "four" },
{ "id": 5, "name": "five" },
{ "id": 6, "name": "six" }
],
]
I'm trying to use jquery templates to create the following HTML
<div class="row">
<div class="cell">
<span>1</span> : <span>one</span>
</div>
<div class="cell">
<span>2</span> : <span>two</span>
</div>
<div class="cell">
<span>3</span> : <span>three</span>
</div>
</div>
<div class="row">
<div class="cell">
<span>4</span> : <span>four</span>
</div>
<div class="cell">
<span>5</span> : <span>five</span>
</div>
<div class="cell">
<span>6</span> : <span>six</span>
</div>
</div>
I am using the following templates with no luck :(
<script id="rowTemplate" type="text/x-jQuery-tmpl">
<div class="row">
{{tmpl "#cellTemplate"}}
</div>
</script>
<script id="cellTemplate" type="text/x-jQuery-tmpl">
<div class="cell">
<span>${id}</span> : <span>${name}</span>
</div>
</script>
The line that calls the template is the following:
$("#rowTemplate").tmpl(arr).replaceAll("#somediv");
I am getting only one row with one cell with no data...
<div class="row">
<div class="cell">
<span></span> : <span></span>
</div>
</div>
What am I doing wrong?
I think the problem is with usage of replaceAll and the missing parameter to tmpl in the template.
Try this(used replaceWith for #someDiv and passed $data as tmpl parameter for child template):
<script type="text/javascript">
var arr =
[
[
{
"id": 1,
"name": "one"
},
{
"id": 2,
"name": "two"
},
{
"id": 3,
"name": "three"
}
],
[
{
"id": 4,
"name": "four"
},
{
"id": 5,
"name": "five"
},
{
"id": 6,
"name": "six"
}
]
];
$(function(){
$("#somediv").replaceWith($("#rowTemplate").tmpl(arr));
});
</script>
<script id="rowTemplate" type="text/x-jQuery-tmpl">
<div class="row">
{{tmpl($data) "#cellTemplate"}}
</div>
</script>
<script id="cellTemplate" type="text/x-jQuery-tmpl">
<div class = "cell"><span>${id}</span>:<span>${name}</span></div>
</script>
<div id="somediv"></div>