Angularjs losing scope in same line ng-repeat - angularjs

I'm having trouble replacing the {{path}} within the template tag in the ng-include. If I put the tag inside the template anywhere else works perfectly, however I need to work within the include-ng to get the base path. Anyone have an idea.
Html with MVC
<div ng-controller='menuCtrl'>
<nav id="menu">
<ul>
<li ng-repeat="item in itens" ng-include="'#(ViewBag.path)Areas/System/scripts/templates/menu.html'" repeat-done></li>
</ul>
</nav>
</div>
App.js
var myApp = angular.module('mobsupplyApp', []).directive('repeatDone', function () {
return function (scope) {
if (scope.$last === true) {
setTimeout(function () {
$("#menu").jarvismenu();
});
}
};
});
myApp.controller('menuCtrl', ['$scope', '$http', function ($scope, $http) {
$http.get(path + "api/menu").success(function (data, status) {
$scope.itens = data;
$scope.path = path;
});
}]);
Template.html
<i class="fa fa-lg fa-fw {{ item.image }}"></i> <span class="menu-item-parent">{{ item.description }}</span>
<ul ng-if="item.itens">
<li ng-repeat="item in item.itens" ng-include="'{{ path }}Areas/System/scripts/templates/menu.html'"></li>
</ul>

Related

angular-ui-tree doesn't work with more than 9 levels

I have a directive that use the angular-ui-tree component inside an asp.net mvc project, it works really great but a major bug appears every time it renders a tree with more than 9 levels.
For this we have an open issue, but is still not merged in master branch, anyway, I need to find a workaround, this is my code:
Directive:
(function () {
"use strict";
angular
.module("app.users")
.directive("columnConfigurationA", [
function () {
return {
restrict: "E",
scope: {
columnConfig: "=columnConfig"
},
link: {
pre: function (scope) {
}
},
controller: ["$http", "$scope", "$uibModal", "modalMsgSrv",
function ($http, $scope, $uibModal, modalMsgSrv) {
$scope.columnConfig = [];
$scope.carePlans = [];
getColumnConfiguration(params, $http).success(function (data) {
$scope.columnConfig = setVisibleColumns(-1, data.columns);
$scope.carePlans = data.carePlans;
});
}],
templateUrl: '/sbusA/ColumnConfigurationA'
};
}]);
function getColumnConfiguration(params, $http) {
var url = "/SbusA/GetColumnConfigurationA";
return $http.get(url, { params: params });
}
})();
HTML:
<div class="plan-edit-cont">
<div class="sorteable">
<script type="text/ng-template" id="nodes_renderer.html">
<div class="checkbox c-checkbox mb0 mt-sm inline align-top">
<label><input type="checkbox" ng-disabled="edition" ng-model="node.show" ng-click="disableChildrens(node)"><span class="fa fa-check"></span></label>
</div>
<div class="text-inverse inline" ui-tree-handle>
{{node.title}}
</div>
<a role="button" class="flow-icon-sort ml-lg mr fr drag-icon draggable" ng-hide="edition" dnd-handle><i class="fa fa-sort" aria-hidden="true"></i></a>
<a role="button" class="flow-icon-plus ml-lg fr drag-icon" ng-hide="edition" ng-click="editVital(node)"><i class="fa fa-pencil" aria-hidden="true"></i></a>
<ul class="sub-questions-list" ui-tree-nodes="" ng-model="node.columnChilds">
<li ng-repeat="node in node.columnChilds" ui-tree-node ng-include="'nodes_renderer.html'">
</li>
</ul>
</script>
<div ui-tree>
<ul style="list-style: none;" ui-tree-nodes="" ng-model="columnConfig" id="tree-root" dnd-list="columnConfig" dnd-allowed-types="['node']">
<li ng-if="node.visibleColumn === true" ng-repeat="node in columnConfig" ui-tree-node ng-include="'nodes_renderer.html'" dnd-draggable="node" dnd-type="'node'" dnd-moved="removeVital(node)"></li>
</ul>
</div>
</div>
</div>
This is the error that I get when I have more than 9 tree levels:
Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations:

How to bind and parse HTML content retrieved from database via Json

I'm using AngularJS 1.5.8.
I'm trying to bind {{card.reading}} in the view, but the data is rendered as text
html
<div ng-app="myApplication" ng-controller="postController as tarot">
<ul>
<li class="card" ng-repeat="card in tarot">
<img class="card" src="app/images/cards/{{card.value}}.png" alt="card.name">
<article>{{card.reading | unsafe}}</article>
</li>
</ul>
</div>`
JavaScript
var app = angular.module('myApplication', []);
app.controller('postController', function($scope, $http, $filter, $sce) {
$scope.$sce = $sce;
var url = './api.php/tarot';
$http.get(url).success(function(response) {
$scope.tarot = php_crud_api_transform(response).tarot;
});
});
app.filter('unsafe', function($sce){
return $sce.parseAsHtml;
});
exemple of JSON
{
"id":1,
"name": "Test",
"value": "1",
"reading": "<h2>Lorem Ipsum</h2><p>Lorem ipsum</p>"
}
Updating your HTML as such should do the trick..
<div ng-app="myApplication" ng-controller="postController as tarot">
<ul>
<li class="card" ng-repeat="card in tarot">
<img class="card" src="app/images/cards/{{card.value}}.png" alt="card.name">
<article ng-bind-html="card.reading"></article>
</li>
</ul>
</div>`
Thank you, it's solved now.
JavaScript
var app = angular.module('myApplication', ['ngSanitize'])
.controller('postController', ['$scope', '$http', '$sce',
function postController($scope, $http, $sce) {
var url = './api.php/tarot';
$http.get(url).success(function(response) {
$scope.tarot = php_crud_api_transform(response).tarot
});
$scope.explicitlyTrustedHtml = $sce.trustAsHtml();
}
]);
and the HTML as you suggested. :)
There is another solution . you can modify you code a little bit and it will work.
<div ng-app="myApplication" ng-controller="postController as tarot">
<ul>
<li class="card" ng-repeat="card in tarot">
<img class="card" src="app/images/cards/{{card.value}}.png" alt="card.name">
<article ng-bind-html="card.reading | unsafe"></article>
</li>
</ul>
</div>`
change your filter to ,
app.filter('unsafe', function($sce) {
return function(text) {
return $sce.trustAsHtml(text);
}
});
This will work.

Angular JS - Nested JSON Driving a Two Level Navigation - How to Alter scope from directive?

I'm new to Angular but enjoying getting to know it! I'm having no problem populating data but I'm stuck on this navigational problem.
I have a sidebar divided into two navigation s. Both are reading from nested JSON of 'areas' and 'reports'. The idea is that the currently selected/clicked item in the left hand list will populate the elements in the right hand list, according to its children in the JSON.
I've got the initial population working fine. It reads the 'areas' and assigns the active area, which displays the reports. I then have a directive which applies css classes on the click event, but how can I get it to also alter the active area?
I'm currently doing scope.activeArea = scope.areas[1];, but this does not work. The index is just there for development; that will be replaced by the index of the clicked element.
My HTML:
<div id="reports-subnav" ng-controller="reportAreasController">
<ul class="subnav-areas" >
<li ng-repeat="x in areas">
<a class="subnav-area-button" href="#" my-cool-directive>
<i class="{{ x.iconClass }}"></i>
</a>
</li>
</ul>
<ul id="nav-subsection" class="subnav-reports">
<li ng-repeat="r in activeArea.reports" id="{{ r.action }}" role="presentation"><span class="{{ r.iconClass }}"></span> {{ r.name }}</li>
</ul>
</div>
And Javascript:
var app = angular.module("focalWeb", []);
app.controller("reportAreasController", ['$scope','$http', function($scope, $http) {
$http.get('<?php echo SITE_ADDR; ?>/data/reportAreas.json').success (function(data){
$scope.areas = data.areas;
$scope.activeArea = $scope.areas[0];
});
}] );
app.directive("myCoolDirective", function() {
return {
restrict: "A",
link: function(scope, elem, attrs) {
$(elem).click(function() {
//var target = $(elem).next(".panel-collapse");
//target.hasClass("collapse") ? target.collapse("show") : target.collapse("hide");
$('.subnav-areas li').removeClass('active');
$(this).parent().addClass('active');
scope.activeArea = scope.areas[1];
});
}
}
});
Thanks!
Edit
Thanks to charlietfl's guidance my code now looks like this:
HTML
<div id="reports-subnav" ng-controller="reportAreasController">
<ul class="subnav-areas" >
<li class="subnav-area" ng-repeat="x in areas">
<a class="subnav-area-button" href="#" ng-click="showReports($event, x.id)">
<i class="{{ x.iconClass }}"></i>
</a>
</li>
</ul>
<ul id="nav-subsection" class="subnav-reports">
<li ng-repeat="r in activeArea.reports" id="{{ r.action }}" role="presentation"><span class="{{ r.iconClass }}"></span> {{ r.name }}</li>
</ul>
</div>
JS
var app = angular.module("focalWeb", []);
app.controller("reportAreasController", ['$scope','$http', function($scope, $http) {
$http.get('<?php echo SITE_ADDR; ?>/data/reportAreas.json').success (function(data){
$scope.areas = data.areas;
$scope.activeArea = $scope.areas[0];
$scope.showReports = function($event, index) {
$scope.activeArea = $scope.areas[index -1];
var theLi = angular.element($event.currentTarget).parent();
theLi.parent().find('li').removeClass('active');
theLi.addClass('active');
}
});
}] );
Edit 2
HTML
<div id="reports-subnav" ng-controller="reportAreasController">
<ul class="subnav-areas" >
<li class="subnav-area" ng-repeat="x in areas" ng-class="{active: x==activeArea}">
<a class="subnav-area-button" href="#" ng-click="showReports($event, x)">
<i class="{{ x.iconClass }}"></i>
</a>
</li>
</ul>
<ul id="nav-subsection" class="subnav-reports">
<li ng-repeat="r in activeArea.reports" id="{{ r.action }}" role="presentation"><span class="{{ r.iconClass }}"></span> {{ r.name }}</li>
</ul>
</div>
JS
var app = angular.module("focalWeb", []);
app.controller("reportAreasController", ['$scope','$http', function($scope, $http) {
$http.get('<?php echo SITE_ADDR; ?>/data/reportAreas.json').success (function(data){
$scope.areas = data.areas;
$scope.activeArea = $scope.areas[0];
$scope.showReports = function($event, item) {
$scope.activeArea = item;
}
});
}] );
Thanks again charlietfl!

all arrays are not showing with angular

This is my controller that will fetch all notes for my main page. When I console.log($scope.allNotes) all my arrays are logged but when I render with my HTML only 1 array shows up
exports.allNotesController = function ($scope, $http, $notes) {
$notes.fetchNotes().then(function (result) {
var data = result.data
data.filter(function (notes) {
$scope.allnotes = notes.notes
console.log($scope.allnotes)
})
})
}
my HTML:
<section class="row all-notes">
<h1>All Notes</h1>
<div class="allNotes">
<ul ng-repeat="notes in allnotes">
<li>{{ notes }}</li>
</ul>
</div>
</section>
<a class="btn btn-default" href="#/login">Login</a>
I solved it in a very hacky way.
Heres my new controller
exports.allNotesController = function ($scope, $http, $notes) {
$notes.fetchNotes().then(function (result) {
$scope.allnotes = result.data
})
}
my HTML, this is where the magic happens. lol
<ul ng-repeat="notes in allnotes track by $index">
<li>{{ notes.notes.toString() }}</li> // i had no idea I can use toString() here
</ul>

AngularJS How to get data to controller via $rootScope?

I'm working on an mobile app and I'm having problems with getting data to the controller. What i do is i get the data from a service and that works well (on routing this is '/' or root directory):
var listdnModule = angular.module('listdn', []);
listdnModule.factory('getActiveDnService', ['$http', function ($http) {
return {
getActiveDnSvc: function (izvajalecID) {
return $http({ method: 'POST', url: 'svc.aspx/getActiveDN', data: "{'izvajalecID':" + "'" + izvajalecID + "'}", cache: true });
}
};
}]);
listdnModule.controller('listdnCtrl', ['$scope', '$http', 'getActiveDnService','$rootScope', function ($scope, $http, svc, $rootScope) {
$scope.mjav = 1;
svc.getActiveDnSvc($scope.mjav).success(function (data) {
$rootScope.dnlist = data.d;
$scope.listdn = data.d;
});
}]);
So this works fine. It sets the data to the rootScope and to localscope and reads it from local scope.
Then i'm linking the list of Costumers to costumerdetail. The route settings are like this:
mSvc.config(['$routeProvider',
function ($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'tmpl/listdn.html',
controller: 'listdnCtrl'
}).
when('/settings', {
templateUrl: 'tmpl/nastavitve.html',
controller: 'settings'
}).
when('/dndetail/:dnid', {
templateUrl: 'tmpl/dndetail.html',
controller: 'dndetailCtrl'
}).
otherwise({
redirectTo: '/'
});
}]);
The error comes after i try to get dndetail. I get the right ID from $routeParams but i dont get the data in the right time. The code is this:
var dndetail = angular.module('dndetail', []);
dndetail.controller('dndetailCtrl', ['$rootScope', '$scope', '$routeParams', function ($rootScope, $scope, $routeParams) {
console.log($rootScope.dnlist[0]);
$scope.datal = $rootScope.dnlist;
$scope.id = $routeParams.dnid;
for(var i = 0; i <= datal.length; i++) {
if (datal[i].ID === $scope.id) {
$scope.data = datal[i];
}
}
}]);
And this is the error i get:
As you can see the console.log gets the object and prints the output (I masked it because it's company data) while datal is undefined. The special AngularJS tab in chrome DevTools also says the data is there:
And for the end the template of the view that doesnt get data:
<ul ng-controller="dndetailCtrl" class="list-group">
<li class="list-group-item">
<div class="row info-row-li">
<div class="pull-left">Naslov</div>
<div class="pull-right">
<a ng-href="https://maps.google.com/?q={{ data.Ulica }} {{ data.Posta }} {{ data.Kraj }}">
{{ $root.dnlist[1].Ulica }}<br />
{{ data.Posta }} {{ data.Kraj }}<br />
{{ data.Drzava }}</a>
</div>
</div>
</li>
<li class="list-group-item">
<div class="row info-row-li">
<div class="pull-left">Datum izvedbe</div>
<div id="kupec-pe" class="pull-right">{{ data.DatumIzvedbe }}</div>
</div>
</li>
<li class="list-group-item">
<div class="row info-row-li">
<div class="pull-left">Datum naloga</div>
<div id="kupec-dst" class="pull-right">{{ data.DatumNaloga }}</div>
</div>
</li>
<li class="list-group-item">
<div class="row info-row-li">
<div class="pull-left">Opis:</div>
<div id="kupec-komerc" class="pull-right">{{ data.Opis }}</div>
</div>
</li>
<li class="list-group-item">
<div class="row info-row-li">
<div class="pull-left">Šifra dejavnosti:</div>
<div id="kupec-sif" class="pull-right">{{ data.sifDej }}</div>
</div>
</li>
<li class="list-group-item">
<div class="row info-row-li">
<div class="pull-left">Šifra dejavnosti:</div>
<div id="Div1" class="pull-right">{{ data.DatumIzvedbe }}</div>
</div>
</li>
</ul>
Any ideas?
UPDATE
This is the new controller:
dndetail.controller('dndetailCtrl', ['$rootScope', '$scope', '$routeParams', function ($rootScope, $scope, $routeParams) {
$rootScope.dnlist;
$scope.id = $routeParams.dnid;
for (var i = 0; i <= $rootScope.dnlist.length; i++) {
if ($rootScope.dnlist[i].ID === $scope.id) {
$scope.data = $rootScope.dnlist[i];
}
}
}]);
still doesnt work. From an array of elements i want to get one element by id and then save it to data so i can read from data. For loop doesnt get the data (unindentified dnlist) but if i bind {{ $root.dnlist[1].Property }} in the template it works.
I don't think problem is fixed by this answer and tried to delete it, I have undelete it as it has been referred in a comment.
$http in angularjs returns a promise, you can't use the promise directly to access the data, check this answer where it answer something very similar.
If anyone was wondering the problem was with the equality operator. If I change === with the one that checks type == i dont get the TypeError: Cannot read property 'ID' of undefined error any more. Since this is the solution to the problem I'd like to have an explanation also. I'm a javascript beginner to be true and if someone got an idea what happened here, I'd very much like to know the explanation.
The new controller that works:
dndetail.controller('dndetailCtrl', ['$rootScope', '$scope', '$routeParams', function ($rootScope, $scope, $routeParams) {
$rootScope.dnlist;
$scope.id = $routeParams.dnid;
for (var i = 0; i <= $rootScope.dnlist.length; i++) {
if ($rootScope.dnlist[i].ID == $scope.id) {
$scope.data = $rootScope.dnlist[i];
}
}
}]);

Resources