Generating Dynamic bootstrap Menus with Angular - javascript

I am trying to create bootstrap navbar menus dynamically using Angular.
The source data for the menu comes from json which looks like below:
{
"Menu": [
{
"title": "Individual",
"url": "#",
"subMenu": [{
"title": "Individual Address",
"url": "http://www.w3schools.com/html/default.asp",
"subMenu": []
}]
},
{
"title": "Organisation",
"url": "#",
"subMenu": [{
"title": "Organisation Address",
"url": "http://www.w3schools.com/html/default.asp",
"subMenu": []
},{
"title": "Organisation Contact",
"url": "http://www.w3schools.com/html/default.asp",
"subMenu": []
},{
"title": "Organisation Sector",
"url": "http://www.w3schools.com/html/default.asp",
"subMenu": []
}]
},
{
"title": "Return",
"url": "http://www.w3schools.com/js/default.asp",
"subMenu": []
}
]
}
As you can see that there are nested items so we need to have dropdown menus in our navigation bar.
I have created a directive to generate the dynamic menus (I have used the directive found here as a starting point). The modified version of the directive looks like:
app.directive('tree', function ($compile) {
return {
restrict: 'E',
terminal: true,
scope: { val: '=', parentData:'=' },
link: function (scope, element, attrs) {
if (scope.val.subMenu !== undefined && scope.val.subMenu.length > 0) {
template = '<li class="dropdown"> '+
' <a class="dropdown-toggle" data-toggle="dropdown" href="{{val.url}}">{{val.title}} '+
' <span class="caret"></span></a> '+
' <ul class="dropdown-menu"> '+
' <div ng-repeat="item in val.subMenu"> '+
' <tree val="item" parent-data="val.subMenu"></tree> '+
' </div>'
' </ul> '+
'</li> ';
}
else
{
template = '<li>{{val.title}}</i> ';
}
var newElement = angular.element(template);
$compile(newElement)(scope);
element.replaceWith(newElement);
}
}
Below is the html code where I am using this directive
<div class="container">
<div class="row">
<nav class="navbar navbar-default">
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<div ng-repeat="menu in menuFamily.Menu">
<tree val="menu"></tree>
</div>
</ul>
</div>
</nav>
</div>
</div>
The menus are generated but because I am using div tags for ng-repeat, the menus are not rendered properly. However, if I remove the div tags from the generated html everything works fine. So my question how can I achieve what I want without using div tags.
You can also find my sample code at plunker
P.S. I am new to Angular world and I have a very basic knowledge of directives.

If I understand your question correctly, there are two things you need to do:
Correct usage of ng-repeat
ng-repeat can be applied directly to your tree directive. Change
<div ng-repeat="...">
<tree ...>
</div>
To
<tree ng-repeat="..." />
Both in your html file and in your directive's template property.
This will apply the proper styles to your menu.
Import Bootstrap js and initialize dropdowns
Because Angular will modify the DOM to add your dropdown's HTML, you need to manually initialize the dropdowns once they have been added.
Call $('.dropdown-toggle').dropdown() once your elements have been added.
Nevermind, just add the Bootstrap JS in your page, seems it properly initializes by itself.
<script src="http://code.jquery.com/jquery-2.1.4.min.js" data-semver="2.1.4" data-require="jquery#*"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
Editied plunkr is here.

Related

How to get angular js expressions to consider css values from the api and apply it to its card

I'm creating pokemon cards that take data from the API. How can I get the CSS of a particular card get applied to its respective card from the API directly just like the information which I've rendered using angular-js.
I'm done retrieving the data like name, description and image.I used angular-js directives to get the data.Similarly, the API consists of CSS styling for each of their respective cards.How can I get the CSS of a particular card get applied to its respective card from the API directly just like the information which I've rendered using angular-js.
JSON:
[{
"cardColors": {
"bg": "#47C67B",
"imgbg": "#80EDAC",
"tagbg": "#8edbae",
"text": "#ffffff",
"textbg": "#66CF91"
},
"description": "Bulbasaur is a small quadruped Pokemon that has turquoise skin with darker teal patches ",
"name": "Bulbasaur",
"sprite": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/1.png",
"tag": "Grass"
}, {
"cardColors": {
"bg": "#f88321",
"imgbg": "#ffb047",
"tagbg": "#fab275",
"text": "#ffffff",
"textbg": "#f99847"
},
"description": "Pikachu is a Mouse Pokemon and the evolved form of
Pichu. Pikachu's tail is sometimes struck by lightning as it raises it to
check its surroundings.",
"name": "Pikachu",
"sprite": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/25.png",
"tag": "Electric"
}]
JS:
var app = angular.module('myApp', []);
app.controller('pokemonCtrl', function($scope, $http) {
$http.get("pokemondata.json").then(function (response) {
$scope.myData = response.data;
});
});
HTML:
<div class="container" ng-app="myApp" ng-controller="pokemonCtrl">
<div class="row">
<div class="col-sm-4" ng-repeat="x in myData">
<h4>{{x.name}}</h4><br/>
<p>{{x.description}}</p><br/>
<img class="cards" ng-src="{{x.sprite}}"><br/>
</div>
</div>
</div>
You should use ngStyle to apply styles from your controller data to your list elements. Something like:
<div class="row">
<div class="col-sm-4" ng-repeat="x in myData" ng-style="{'background-color': x.bg, color: x.text}">
<h4>{{x.name}}</h4><br/>
<p ng-style="{'background-color': x.textbg}">{{x.description}}</p><br/>
<img class="cards" ng-src="{{x.sprite}}"><br/>
</div>
</div>

How to call out multiple JSON objects in Angular

I am trying to call multiple objects from my JSON file for various different sections on my site. As it stands i have the jobs and a misc section for section titles etc. With my HTML i have the following
<h2>{{job.jobTitle}}</h2>
This works fine. However the misc section doesn't display any content
<h1>{{title.widgetTitle}}</h1>
plunkr
"jobs": [
{
"jobTitle": "Senior Accountant",
"sector": "Accounting & Finance",
"link": "/jobs/1"
},
],
"title": [
{"widgetTitle": "Latest Jobs"}
]
HTML
<div class="tickr-container" data-ng-controller="tickCtrl">
<div>
<h1>{{title[0].widgetTitle}}</h1>
</div>
<div>
<h3>{{date | date:'fullDate' : 'GMT'}}</h3>
<ul ng-mouseover="stopAuto()" ng-mouseleave="startAuto()" class="tickrSlider">
<li class="tickrSlider-slide" ng-class="{'job-active' :isActive($index)}" data-ng-repeat="job in jobs">
<div class="tickrSlider-inner">
<h2>{{job.jobTitle}}</h2>
<p>{{job.sector}}</p>
<a class="tickrSlide-info" href="{{job.link}}">{{job.link}}</a>
</div>
</li>
</ul>
Shouldn't you reference title[0].widgetTitle?
<h2>{{job.jobTitle}}</h2> appears fine since you reference the job object from data-ng-repeat="job in jobs"

ng-repeat disable my div

I for my stage have to modifie a web site for that i need angularjs i wanted to use the command ng-repeat to display some documentation but when i add ng-repeat in the div it "destroy" it and i cant figure out why...
So there is the code hope u can help me.
There is my js
App.controller('doccontroller', [ function(){
return {
scope: {},
restrict: 'A',
link: function ($scope){
$scope.docs = [
{
"id_section" : 0,
"description": "RANDOM STUFF",
"source": [
{
"python": "TEXTE",
"ruby": "TEXTE",
"javascript": "TEXTE"
}
]
},
{
"id_section" : 1,
"description": "RANDOM STUFF",
"source": [
{
"python": "TEXTE",
"ruby": "TEXTE",
"javascript": "TEXTE"
}
]
},
{
"id_section" : 2,
"description": "RANDOM STUFF",
"source": [
{
"python": "TEXTE",
"ruby": "TEXTE",
"javascript": "TEXTE"
}
]
}
]
}
}
}
])
`There is my route to "include" the controller
$routeProvider.when '/docs',
templateUrl : config.BaseHtml+'/Page/docs.html'
controller : 'doccontroller'
`
and to finish the html :)
<div id="api-docs">
<div id="methods">
<div class="languages">
<a class="language selected" data-lang="ruby" href="#">Ruby</a>
<a class="language" data-lang="python" href="#">Python</a>
<a class="language" data-lang="php" href="#">PHP</a>
</div>
<div>
<div class="method" id="intro">
<div class="method-section clearfix">
<div class="method-description" ng-repeat="doc in docs">
<h3>Introduction</h3>
<p>
{{doc.description}}
</p>
</div>
<div class="method-example">
<pre>
<code class="ruby"># All this code is just folololol
React.api_key = "In here goes your api key!"</code><code class="python"># All this code is just for demonstration purposes
react.api_key = "In here goes your api key!"</code><code class="php"># All this code is just for demonstration purposes
React::setApiKey("In here goes your api key!");</code>
</pre>
</div>
</div>
</div>
</div>
</div>
</div>
So to say it again, what i need to do is to fill create 1 div / id_section and to fill it with the
descrition for now.
Change:
ng-repeat="docs in docs"
to:
ng-repeat="doc in docs"
Also, in your code you have a call to {{ doc.des }}, which probably should be {{ doc.description }}

How to hide an element in angular js if this is repeatable?

I have created a code and I'm repeatable in text with icon.
You see the img but I want to hide to this actually I show this image if I have a anchor link than show if I have no link than not show this image. Is this possible in angular js?
My code is:
Angular Code is
var myAppMy = angular.module('myFapp', []);
myAppMy.controller('myControler', function($scope) {
$scope.items = [
{
"title":"Book" ,"subtitle":[
{"subtitle":"PanchTantra ",
"description":"Kids Books",
"authorName":"Kisna"
}
],
"description": "Some Book is very Good."
},
{
"title":"Mediciane Book" , "subtitle":[
{"subtitle":"Pharmacy", "description":"This book is related to Docotrs"}
],
"description": "This book is very hard"
},
{
"title":"Reciape Book" , "subtitle":[
{"subtitle":"Khana Khajana", "description":"This book is related to Foods"}
],
"description": "This book is nice..."
},
{
"title":"Computer Book" , "subtitle":[
{"subtitle":"BCA MCA", "description":"This book is related to Education"}
],
"description": "This book is very beautiful."
}
];
});
HTML Code is
<body ng-app="myFapp">
<ul ng-controller="myControler">
<li ng-repeat= "item in items">
<div>{{item.title}} </div>
<div>{{item.description}}</div>
<ul>
<li ng-repeat="subtitle in item.subtitle">
<div>{{subtitle.subtitle }} <img src="https://www.gravatar.com/avatar/76e03db06bb6dcf24f95bf4d354486db?s=32&d=identicon&r=PG" />{{ subtitle.authorName}} </div>
<div>{{subtitle.description}} this is </div>
</li>
</ul>
</li>
</ul>
</body>
Plunkr link is
Is this what you want to do ?
<div>{{subtitle.subtitle }} <img src="https://www.gravatar.com/avatar/76e03db06bb6dcf24f95bf4d354486db?s=32&d=identicon&r=PG" />{{ subtitle.authorName}} </div>
http://plnkr.co/edit/6tnGlTLeLUZdiGCUHDFV?p=preview
The ng-show directive allows you to show or hide the given HTML element based on the expression provided.
See the Official doc

AngularJS and ng-class

I have the next html code:
<div class="collapse navbar-collapse menu-sidebar">
<ul class="nav nav-stacked" id="menu-bar">
<li class="panel dropdown" ng-repeat="m in menuSidebar.links">
<a data-toggle="collapse" data-parent="#menu-bar" data-target="#{{'menuSidebar' + $index}}" href="">
{{m.text}}
</a>
<div id="{{'menuSidebar' + $index}}" class="panel-collapse collapse submenu-sidebar">
<ul class="nav nav-stacked">
<li ng-repeat="s in m.sub" ng-class="{active: s.active}">{{s.text}}</li>
</ul>
</div>
</li>
</ul>
</div>
And the next json:
$scope.menuSidebar = {
"links": [
{
"text": "Total",
"sub": [
{
"active": true,
"link": "#",
"text": "General"
},
{
"active": false,
"link": "#",
"text": "Cargos"
},
{
"active": false,
"link": "#",
"text": "Prestadora"
},
{
"active": false,
"link": "#",
"text": "Factura"
}
]
},
{
"text": "Departamento",
"sub": [
{
"active": false,
"link": "#",
"text": "Costos"
},
{
"active": false,
"link": "#",
"text": "Tiempos"
}
]
}
]
};
I would like to define the class of the div in the case that any of the child is active==true.
<div id="{{'menuSidebar' + $index}}" ng-class="active: ..." class="panel-collapse collapse submenu-sidebar">
How to loop through all the children and determine the class? It is possible use ng-class in this case?
Thanks
no need to parse all the children define a "some_active" variable in your controller by doing
<li ng-repeat="s in m.sub" ng-class="{active: s.active}" ng-init="$parent.some_active=$parent.some_active||s.active">{{s.text}}</li>
then you can use
<div id="{{'menuSidebar' + $index}}" ng-class="{active:some_active}" class="panel-collapse collapse submenu-sidebar">
this solution requires that you also modify some_active variable on the on click handlers of your li
other solutions if you don't want to do that would be to have
<div id="{{'menuSidebar' + $index}}" ng-class="{active:someActive()}" class="panel-collapse collapse submenu-sidebar">
where "active:someActive" would be a function defined in your scope that traverses your submenu tree and returns true or false when some options are active.
bottom line it deppends on your layout and whether you prefer notifications or dirty check
I would create a scope function that takes in the link in question:
$scope.hasActiveChildren = function(link) {
for(var i=0; i < link.sub.length; i++) {
if(link.sub[i].active) {
return true;
}
}
return false;
};
And then add it to the markup as you had above:
<div id="{{'menuSidebar' + $index}}" ng-class="{'active': hasActiveChildren(m)}" class="panel-collapse collapse submenu-sidebar">
Here is the JSFiddle

Categories

Resources