Passing JSON data in pattern | PatternLab - javascript

I want to include an atomic pattern and want to pass data from a JSON array below is code and JSON file.
anchor-link.mustache
{{ label }}
footer-nav.mustache
<ul class="menu vertical">
{{# footerNav }}
<li>{{> atoms-anchor-link(url:url, label : label, class : class) }}</li>
{{/ footerNav }}
</ul>
JSON from where i want to populate anchor mustache
{
"footerNav": [{
"label": "Shop",
"url": "#",
"class": "body-copy"
}, {
"label": "Pods",
"url": "#",
"class": "all-caps-large"
}]
}
Output
<ul class="menu vertical">
<li>
</li>
<li>
</li>
</ul>
Pattern Lab is generating correct HTML and creates anchors but no values are populating in anchors.
Thanks in advance!!!!

You have called wrong pattern here.
<li>{{> atoms-anchor-link(url:url, label : label, class : class) }}</li>
Correct pattern is.
<li>{{> atoms-anchor-link}}</li>
This will work.

Related

Render ng-zorro tags from component

I'm trying to render a <li> with some ng-zorro tags, I try with innerHTML but when i enter to the page this fails, I want to show differents menu's if the user get in a specific application (route)
I have my JSON like this
menuApp = [
{
"app": "requerimientos",
'menu': '\
<li nz-menu-item nzMatchRouter>\
<a routerLink="/applications/dashboard/requerimientos/crear-pedido">Crear pedido</a>\
</li>\
<li nz-menu-item nzMatchRouter>\
<a routerLink="/applications/dashboard/requerimientos/verificar-pedido">Verificar pedido</a>\
</li>\
'
}
]
and in my HTML
<li nz-submenu nzOpen nzTitle="MenĂº {{activeChild}}" nzIcon="appstore" *ngIf="activeChild != ''">
<div *ngFor="let app of menuApp; index as i">
<ul *ngIf="app.app === activeChild">
<div [innerHTML]="app.menu"></div>
</ul>
</div>
</li>
but when i render the page the <li> print without any ng-zorro tag or class
hope someone can help me
Angular doesn't work that way. Custom directives (like nzMatchRouter) cannot be shoehorned in with an innerHTML. You have to instruct the parser to compile the HTML after it's been added. But even still, there are more efficient, angular-centric methods you can use - like keeping your menu as a simple array of text/url values and using *ngFor to iterate them. That way the <li> directives are compiled at runtime
menuApp = [
{
"app": "requerimientos",
'menu': [
{text: "Crear pedido", url: "/applications/dashboard/requerimientos/crear-pedido" },
{text: "Verificar pedido", url: "/applications/dashboard/requerimientos/verificar-pedido" }
]}
Then your HTML would be like
<li nz-submenu nzOpen nzTitle="MenĂº {{activeChild}}" nzIcon="appstore" *ngIf="activeChild != ''">
<div *ngFor="let app of menuApp; index as i">
<ul *ngIf="app.app === activeChild">
<li *ngFor="item in app.menu" nz-menu-item nzMatchRouter>
<a [routerLink]="item.url">{{item.text}}</a>
</li>
</ul>
</div>
</li>

Filter angular js data source inside parent and child nodes

I have created a tree view in angular js using ng-repeat. I have also added a filter to filter my data source. I am able to filter the parent nodes and the resource nodes as what I expected, but my problem is I could not achieve the child node filtering as I expected. This is the picture of my current development status.
Img 4 Shows the current ststus of filtering my child nodes, but my exact requirement is like that in Img 5. i.e, on filtering a node if there is a child node present, only that child node and its parent should apperar, all the remaining child nodes must be hidden. What should I do for that. Here is my code snippet.
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script>
angular.module("app", [])
.controller('MainController', function ($scope) {
$scope.ObjectData = { "name": "Main Object 1",
"ParentObject": [
{
"name": "Parent Object 1",
"ChildObject": [
{"name": "Child Object 11"},
{"name": "Child Object 12"}
]
},
{
"name": "Parent Object 2",
"ChildObject": [
{"name": "Child Object 21"},
{"name": "Child Object 22"}
]
}
],
"resources": [
"Resource 1", "Resource 2"
]
}
});
</script>
</head>
<body>
<div ng-app="app" ng-controller="MainController">
<input type="text" placeholder="search" ng-model="search">
<ul>
<li>
<a>
<span>{{ ObjectData.name }}</span>
</a>
<ul>
<li ng-repeat="subItem in ObjectData.ParentObject | filter:search">
<a>
<span>{{ subItem.name }}</span>
</a>
<ul>
<li ng-repeat="childItem in subItem.ChildObject">
<a>
<span>{{ childItem.name }}</span>
</a>
</li>
</ul>
</li>
</ul>
<ul>
<li ng-repeat="resources in ObjectData.resources | filter:search">
<a>
<span>{{ resources }}</span>
</a>
</li>
</ul>
</li>
</ul>
</div>
</body>
</html>
After putting some more effort, I just created a simple logic to implement my requirement. I'm posting the solution because this might be helpful for someone.
I just added an ng-if inside my child item div. It displays the div content based on two condition.
The individual child object should be visible if the search key contains the characters inside the div.
All the child elements must be visible if the search key consists of the characters in the parent node.
Here is my final code.
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script>
angular.module("app", [])
.controller('MainController', function ($scope) {
$scope.ObjectData = { "name": "Main Object 1",
"ParentObject": [
{
"name": "Parent Object 1",
"ChildObject": [
{"name": "Child Object 11"},
{"name": "Child Object 12"}
]
},
{
"name": "Parent Object 2",
"ChildObject": [
{"name": "Child Object 21"},
{"name": "Child Object 22"}
]
}
],
"resources": [
"Resource 1", "Resource 2"
]
};
$scope.IsChildObjectVisible = function(parent, child){
var searchKey = $scope.search;
var returnVal = true;
if(undefined != searchKey && null != searchKey && searchKey.length > 0){
returnVal = ((child.name.toLowerCase().indexOf(searchKey.toLowerCase()) > -1) || //Search key is present in a child node then that node is visible
(parent.name.toLowerCase().indexOf(searchKey.toLowerCase()) > -1)); //Search key is present in the parent node so all the child nodes inside that are visible
}
return returnVal;
}
});
</script>
</head>
<body>
<div ng-app="app" ng-controller="MainController">
<input type="text" placeholder="search" ng-model="search">
<ul>
<li>
<a><span>{{ ObjectData.name }}</span></a>
<ul>
<li ng-repeat="subItem in ObjectData.ParentObject | filter:search">
<a><span>{{ subItem.name }}</span></a>
<ul>
<li ng-repeat="childItem in subItem.ChildObject" ng-if="IsChildObjectVisible(subItem, childItem)">
<a><span>{{ childItem.name }}</span></a>
</li>
</ul>
</li>
</ul>
<ul>
<li ng-repeat="resources in ObjectData.resources | filter:search">
<a><span>{{ resources }}</span></a>
</li>
</ul>
</li>
</ul>
</div>
</body>
</html>
HTML:
<li ng-repeat="childItem in subItem.ChildObject" ng-if='$filter(subItem.ChildObject, search).length == 0 || childItem.name == search'>
<a>
<span>{{ childItem.name }}</span>
</a>
</li>
Javascript:
.controller('MainController', function ($scope, $filter) {
$scope.$filter = $filter('filter');
//other stuff...
});

Loop through an array from JSON using Angular JS

I am trying to loop through an array from JSON and display the contents more like a side menu. I wrote something like
<ul ng-repeat="(key, value) in menuList.Menu">
<li>{{key}}</li>
<ul ng-repeat="(key, value) in value">
<li> {{key}}</li> //second key
<ul ng-repeat="(key, value) in value">
<li> {{key}}</li>
<ul ng-repeat="(key, value) in value">
<li> {{key}} : {{value}}</li>
</ul>
</ul>
</ul>
</ul>
The problem is my second key has both object and array. How do I display the value of Object and loop/ng-repeat just through the array. I cannot modify it with this as it will display the entire content of the array.
<li> {{key}} : {{value}}</li>
A part of my JSON for better understanding is given below:
{
"class": 99,
"mode" : 0,
"Menu": [{
"MenuNum": 1,
"MenuItems": [{
"ItemNum": 0,
"ItemDesc": "Main Menu",
"ActionCode": "-",
"ActionInst": ""
} , {
"ItemNum": 1,
"ItemDesc": "BBQ",
"ActionCode": "M",
"ActionInst": "0992"
}, {
"ItemNum": 2,
"ItemDesc": "Beverages",
"ActionCode": "M",
"ActionInst": "0992"
}]
},{
"MenuNum": 2,
"MenuItems": [{
"ItemNum": 0,
"ItemDesc": "Sub Menu",
"ActionCode": "-",
"ActionInst": ""
}, {
"ItemNum": 1,
"ItemDesc": "BBQTYPE1",
"ActionCode": "P",
"ActionInst": "0996"
}, {
"ItemNum": 2,
"ItemDesc": "BeveragesTYPE1",
"ActionCode": "P",
"ActionInst": "0998"
}]
}]
}
I want the sidebar more like
Presuming at the moment that you just want the ng-repeat logic, this may be what you are looking for:
<ul ng-repeat="topMenu in menuList.Menu">
<li>
{{$index}}
<ul>
<li>
MenuNum: {{topMenu.MenuNum}}
</li>
<li> MenuItems
<ul ng-repeat="submenu1 in topMenu.MenuItems">
<li>
{{$index}}
<ul>
<li>ItemNum: {{submenu1.ItemNum}}</li>
<li>ItemDesc: {{submenu1.ItemDesc}}</li>
<li>ActionCode: {{submenu1.ActionCode}}</li>
<li>ActionInst: {{submenu1.ActionInst}}</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
If you then want a relatively easy way to do the menu opening/closing, you would probably want to put all this into an Angular accordion. I can probably help you with that if you want.
It looks like you're trying to create a list with nested children. How about a recursive pattern which uses ng-include recursively to display all the nested children? Something like this:
<script type="text/ng-template" id="menuTree">
{{ menuItem.name }}
<ul ng-if="menuItem.children">
<li ng-repeat="menuItem in menuItem.children" ng-include="'menuTree'"></li>
</ul>
</script>
<ul>
<li ng-repeat="menuItem in menuItems" ng-include="'menuTree'"></li>
</ul>
I'm using a slightly different data structure to your code, but you should get the idea. Here's a demo: http://jsfiddle.net/mmmxh8kq/
EDIT:
If the data is as simple as the JSON you posted and you don't need a recursive menu, you could just try this:
<ul>
<li ng-repeat="menus in menuList.Menu">
{{ menus.MenuNum }}
<ul>
<li ng-repeat="menuItems in menus.MenuItems">
{{ menuItems.ItemDesc }}
</li>
</ul>
</li>
</ul>
Demo: http://jsfiddle.net/n4mo80od/

handlebar - unable to loop through data

I'm trying to apply the below model to a handlebar template to get a simple list , but I guess
either the data hierarchy or the way I'm trying to loop through the data
model may be incorrect.
data.js
{
"categories":[
{
"games":{
"action":{
"game":{
"name":"Game 1",
"Description":"Description 1"
},
"game":{
"name":"Game 2",
"Description":"Description 2"
}
}
}
},
{
"movies":{
"fantasy":{
"movie":{
"name":"Movie 1",
"Description":"Description 1"
},
"movie":{
"name":"Movie 2",
"Description":"Description 2"
}
}
}
}
]
}
template
<ul id="categories">
<li> Games
<ul class="subcategories">
{{#each categories}}
...........
{{/each}}
</ul>
</li>
</ul>
I'd like to get a simple list (see below)
<ul id="categories">
<li> Games
<ul class="subcategories">
<li> Action
<ul>
<li>Game 1</li>
<li>Game 2</li>
</ul>
</li>
</ul>
</li>
<li> Movies
<ul class="subcategories">
<li> Fantasy
<ul>
<li>Movie 1</li>
<li>Movie 2</li>
</ul>
</li>
</ul>
</li>
</ul>
Any help is greatly appreciated.
Your data structure doesn't really represents your expected output.
The structure should be something like this:
data (object)
categories (array)
category (object)
category name
subcategories (array)
subcategory (object)
subcategory name
items (array)
item (object)
item name
item description
Note: I called the innermost array items instead of games/movies/etc, so it's easier to use it in the template.
You can see my implementation in this jsfiddle.

Complex jQuery templates

Using jQuery templates is easy for some simple data structures.
<script type="jquery/x-jquery-tmpl" id="myTemplate">
<li> ${Element} </li>
</script>
var elements = [
{ Element: "Hydrogen" },
{ Element: "Oxygen" },
{ Element: "Nitrogen" }
];
$("#elementsPlaceholder").replaceWith($("#myTemplate").tmpl(elements));
But if I need a template for more complex data? Something like:
<script type="jquery/x-jquery-tmpl" id="myTemplate">
<div> ${Molecule} </div>
consists of:
<ul>
<li> ${Element} </li>
</ul>
</script>
How can apply data to that? Is it possible? Could you show me an example?
<ul>
<li> ${Element} </li>
</ul>
should use {{each}}
<ul>
{{each Elements}}<li>${$value.Element}</li>
</ul>
and then you pass in both the molecule and the elements
$("#elementsPlaceholder").replaceWith($("#myTemplate").tmpl({
Molecule: ...
Elements: [{ Element: "Hydrogen" }, ...]
}))

Categories

Resources