NgRepeat, JSON, angularJS - no duplicates allowed - via template in directive
UPDATE:
I found that if I pass the JSON file in the controller like this:
controller('dynamicMenuCtrl', ['$scope', function ($scope) {
$scope.mainmenu2 = [
{
"id": "bananas",
"title": "Bananas",
"href": "#/bananas",
"li-class": "menu-element"
},
{
"id": "apples",
"title": "Apples",
"li-class": "dropdown"
"submenu": [
{
"id": "apple-lot",
"title": "Apples lots",
"href": "#/apples/lot"
},
{
"id": "apple-series",
"title": "Apples series",
"href": "#/apples/series"
}
]
},
{
"id": "cherries",
"title": "Cherries",
"href": "#/cherries",
"li-class": "menu-element"
}
]
});
instead of getting it via $ http.get
my navigation bar is working correctly. I call it in my HTML as:
<li ng-repeat=item in mainmenu2>"
UPDATE 2:
If you are using an MVC app you must register JSON
file inWeb.config
<system.webServer>
<staticContent>
<mimeMap fileExtension=".json" mimeType="application/json; charset=UTF-8"/>
</staticContent>
</system.webServer>
Then everything will be fine
I have a problem, I have a JSON file:
{
"mainmenu": [
{
"id": "bananas",
"title": "Bananas",
"href": "#/bananas",
"li-class": "menu-element"
},
{
"id": "apples",
"title": "Apples",
"li-class": "dropdown"
"submenu": [
{
"id": "apple-lot",
"title": "Apples lots",
"href": "#/apples/lot"
},
{
"id": "apple-series",
"title": "Apples series",
"href": "#/apples/series"
}
]
},
{
"id": "cherries",
"title": "Cherries",
"href": "#/cherries",
"li-class": "menu-element"
}
]
}
I want to create a navigation bar from this JSON file. I am using AngularJS for this (only Angular is allowed in this case).
I created a controller to receive this JSON file:
angular.module('dynamic-menu').controller('dynamicMenuCtrl', ['$scope', '$http', function ($scope, $http) {
$http.get('MenuItems.json').success(function (data) {
$scope.mainmenu = data;
});
Then I want to create a navigation bar in my HTML:
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation" id="nav-bar" style="margin-bottom: 0.5%">"
<div class="container-fluid">
<div class="navbar-header">
<span class="navbar-brand">TITLE</span>
</div>
<div class="collapse navbar-collapse">
<span class="navbar-brand">
<ul class="nav navbar-nav">
<li ng-repeat="item in mainmenu">
<a href="{{item.href}}">{{item.title}}</a>
</li>
</ul> <!-- /.nav navbar-nav -->
</span> <!-- /.navbar-brand -->
</div> <!-- /.navbar-collapse-->
</div> <!-- /.container-fluid-->
</nav>
Then I get the error Error:
[ngRepeat:dupes] Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: item in mainmenu, Duplicate key: string:<, Duplicate value: "<"
I tried to use expression trackby $index
, but this is not the rendering that I want. There are some copies of something, but I don't know what is wrong. Maybe I have something wrong in the JSON file or in the controller?
EDIT: Can you see and edit this plunkr? http://plnkr.co/edit/U1xG2E4ys7SGz7WxBtvq?p=preview
It didn't work either, maybe I'm writing something wrong? I also fixed my JSON file in this post and the error expression
EDIT2: What if I want to render HTML via a directive?
angular.module('dynamic-menu').directive('menuTemplate', function () {
return {
restrict: 'E',
template: "<nav class=\"navbar navbar-inverse navbar-fixed-top\" role=\"navigation\" id=\"nav-bar\" style=\"margin-bottom: 0.5%\">"
+ "<div class=\"container-fluid\">"
+ "<div class=\"navbar-header\">"
+ "<span class=\"navbar-brand\">TITLE</span>"
+ "</div>"
+ "<div class=\"collapse navbar-collapse\">"
+ "<span class=\"navbar-brand\">"
+ "<ul class=\"nav navbar-nav\">"
+ "<li ng-repeat=\"item in mainmenu\">"
+ "<a href=\"{{item.href}}\">{{item.title}}</a>"
+"</li>"
+"</ul> <!-- /.nav navbar-nav -->"
+"</span> <!-- /.navbar-brand -->"
+"</div> <!-- /.navbar-collapse-->"
+"</div> <!-- /.container-fluid-->"
+"</nav>"
};
}]);
EDIT 3: I updated my plunkr and now it works:
http://plnkr.co/edit/U1xG2E4ys7SGz7WxBtvq?p=preview
I created a directive as well and it works as well. I don't know why it works in Plunkr but not in my project :(
source to share
The data you receive is an object that contains a key mainmenu
, which is an array of objects. So in your controller use:
$http.get('MenuItems.json').success(function (data) {
$scope.mainmenu = data.mainmenu;
});
Next, your array mainmenu
contains some object that donot has values href
and title
, but it has a property submenu
(array) that contains href
title values
.
Use this:
<li ng-repeat="item in mainmenu track by $index">
<a ng-if="!item.submenu" href="{{item.href}}">{{item.title}}</a>
<a ng-if="item.submenu">{{item.title}}
<ul ng-repeat="subitem in item.submenu">
<li>
<a href="{{subitem.href}}">{{subitem.title}}</a>
</li>
</ul>
</a>
</li>
source to share
There are several problems in your code:
1) JSON is not valid. This is valid JSON:
{
"mainmenu": [
{
"id": "bananas",
"title": "Bananas",
"href": "#/bananas",
"li-class": "menu-element"
},
{
"id": "apples",
"title": "Apples",
"li-class": "dropdown",
"submenu": [
{
"id": "apple-lot",
"title": "Apples lots",
"href": "#/apples/lot"
},
{
"id": "apple-series",
"title": "Apples series",
"href": "#/apples/series"
}
]
},
{
"id": "cherries",
"title": "Cherries",
"href": "#/cherries",
"li-class": "menu-element"
}
]
}
2) $scope.mainmenu
has a key mainmenu
which is an array, so in the ng-repeat on the key mainmenu
:
<li ng-repeat="item in mainmenu.mainmenu">
Edit: using $http.get
to get json.
See plunkr: " http://plnkr.co/edit/Kcl2uVeWg03bawagdQpm?p=preview "
source to share