Missing attributes from directive - angularjs

I'm trying to get my menu from js directive to my html file with angularJS.
But i dont get all of the attributes like data-toggle, or data-parent or any Id. I'm missing these tags.
data-toggle="collapse"
data-parent="#accordion2"
id="collapseTwo"
Sorry if im unclear, but i've tried to explain it as good as i could.
My js
directives.directive('productTree', ['$compile','$rootScope', function($compile, $rootScope){
return {
scope: {
items: "=",
linkPath : "="
},
template: '<div ng-bind-html="tree"></div>',
replace: true,
link: function (scope) {
var makeTree = function(categories) {
var tree;
var generateNode = function(category, index) {
var children = category.Children.map(function (item, index) {
var childrens = "";
childrens += generateSubNode(item, index)
return childrens
})
var main = "";
main += "<div class=\"accordion-group\">";
main += "<div class=\"accordion-heading\">";
main += "<a class=\"accordion-toggle\" data-toggle=\"collapse\" href=\"#menu-" + category.Item.Id + "\">" + category.Item.Name + "</a>";
main += "</div>";
main += (children.length ? "<div id=\"menu-" + category.Item.Id + "\" class=\"accordion-body collapse\"><div class=\"accordion-inner\">" + children.join("") + "</div></div>" : "");
main += "</div>";
return main;
}
var generateSubNode = function (category, index) {
return '' + category.Item.Name + '';
}
tree = categories.map(function(category, index){
return generateNode(category, index);
});
return tree.join("");
}
scope.tree = makeTree(scope.items);
}
}
}])
My html
<div class="accordion" product-tree items="shop.Menu" link-path="paths.linkPath">
</div>
My output
<div class="accordion-group">
<div class="accordion-heading">
<a class="accordion-toggle" href="#menu-162">Genvägar</a>
</div>
<div class="accordion-body collapse">
<div class="accordion-inner">
Black Friday 2016
Black Friday: iPhone 6S 64GB Prissänkt!
Blåtandshörlurar
iPhone 7/7 Plus
</div>
</div>
</div>
This is how i want it to be
<div class="accordion-group">
<div class="accordion-heading">
<a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion2" href="#collapseOne">
Rubrik 1
</a>
</div>
<div id="collapseOne" class="accordion-body collapse">
<div class="accordion-inner">
Black Friday 2016
Black Friday: iPhone 6S 64GB Prissänkt!
Blåtandshörlurar
iPhone 7/7 Plus
</div>
</div>
</div>

You'll save yourself a lot of trouble if you use the template functionality of angular instead of trying to concatenate your html together piece by piece.
Set your template to something like this (or load it using templateUrl:
<div class="accordion-group" ng-repeat="category in items">
<div class="accordion-heading">
<a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion2" ng-click="toggle()">
{{ category.Item.Name }}
</a>
</div>
<div ng-hide="collapsed" class="accordion-body collapse">
<div class="accordion-inner">
<a ng-repeat="child in category.children" href="{{linkPath}}/catalog/browse/shortcuts/{{ child.Item.URIPath }}/">{{ child.Item.Name }}</a>
</div>
</div>
</div>
Then, change your directive to something like this:
directives.directive('productTree', ['$compile','$rootScope', function($compile, $rootScope){
return {
scope: {
items: "=",
linkPath : "="
},
template: 'the template above (or use templateUrl)',
replace: true,
link: function (scope) {
scope.collapsed = true;
scope.toggle = function(){
scope.collapsed = !scope.collapsed;
};
}
}
}]);
Edit: If you're using, Bootstrap, you might also this out from the AngularUI team.

Related

Show/Hide Angular Directive On Button Click

I have a HTML page with three buttons. I also have two Angular directives. What I'm trying to accomplish is when button a is clicked, I want directive 1 to show and directive 2 to hide. When button 2 is clicked, I want directive 1 to hide and directive 2 to show. Here is are my directives:
.directive('topPosts', function () {
return {
restrict: 'E',
templateUrl: 'topPosts.html',
controller: 'PostsController'
}
});
.directive('otherPosts', function () {
return {
restrict: 'E',
templateUrl: 'otherPosts.html',
controller: 'PostsController'
}
});
here is my controller:
.controller('PostsController', ['$scope', 'PostsFactory', function($scope, PostsFactory) {
$scope.posts = [];
$scope.showTopPosts = true;
$scope.showOtherPosts = false;
$scope.topPosts = function() {
$scope.showTopPosts = true;
$scope.showOtherPosts = false;
};
$scope.otherPosts = function() {
$scope.showTopPosts = false;
$scope.showOtherPosts = true;
};
$scope.areTopPosts = function(posts) {
return posts.privacy === 'public' && posts.comments > 10 && posts.views > 9000 && posts.title.length < 40;
};
$scope.areOtherPosts = function(posts) {
return posts.comments <= 10 && posts.views <= 9000 && posts.title.length >= 40;
};
var init = function() {
PostsFactory.getPosts.success(function(data) {
$scope.posts = data;
});
};
init();
}]);
here is my partial that holds both directives:
<div class="container">
<top-posts ng-show='showTopPosts'></top-posts>
<other-posts ng-show='showOtherPosts'></other-posts>
</div>
and here is my index.html:
<body ng-controller='PostsController'>
<nav class="navbar navbar-inverse navbar-static-top" role="navigation">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<a class="navbar-brand" href="/main"></a>
</div> <!-- END NAVBAR-HEADER -->
</div> <!-- END CONTAINER-FLUID -->
</nav>
<div class="container">
<div class="btn-group" role="group">
<button type="button" class="btn btn-default" ng-click="topPosts()">Top Posts</button>
<button type="button" class="btn btn-default" ng-click="otherPosts()">Other Posts</button>
<!-- <button type="button" class="btn btn-default" ng-click="dailyTopPost()">Daily Top Post</button> -->
</div>
</div>
<div ng-view class='slide-animation'></div>
What's currently happening is the functions are getting called, but the directives are not showing/hiding on the button clicks.
I put work code in a codepen and it seems to be working fine http://codepen.io/arthur_souviron/pen/pEMMaJ/
I think your issue come from the way you store $scope.showTopPosts
and $scope.showOtherPosts. Try to store them inside an object instead of setting them directly under $scope
Eg :
$scope.data = {
showTopPosts: true,
showTopPosts: false
}
and in your template : <top-posts ng-show="data.showTopPosts"></top-posts>
Simply add a div before the directive:
<div class="container">
<div ng-show='showTopPosts'><top-posts ></top-posts></div>
<div ng-show='showOtherPosts'><other-posts ></other-posts></div>
</div>

View not refreshing after successful http.get from factory (chained promises in use)

I have read more tutorials and posts on this particular subject than I care to admit but I still haven't been able to locate a solution. I need the view to refresh after the chained promise returns which is bound to $scope.p.devices. I have tried disabling cached views (still disabled) and a number of other solutions. Hoping someone on here can point me in the proper direction.
HTML:
Device List
<md-card>
<ion-content>
<div class="card-content">
<div class="device-content-detail"
collection-repeat="device in p.devices"
collection-item-height="136px"
collection-item-width="100%">
<div class="card-content">
<h1 class="md-title">
<span>
<i class="fa fa-crosshairs" aria-hidden="true"></i>
Device List
</span>
</h1>
{{device.name}}
</div>
</div>
</ion-content>
</md-card>
<md-list>
<md-card ng-if="!isAnimated" class="card-item" ng-repeat="device in p.devices track by $index">
<md-card-content>
<div class="card-content">
<h1 class="md-title">
<span>
Device List
<i class="fa fa-crosshairs" aria-hidden="true"></i>{{device.name}}
</span>
</h1>
<div class="device-content-detail">
<i class="fa fa-wifi" aria-hidden="true"></i>{{device.connected}}
<i class="fa fa-heartbeat" aria-hidden="true"></i>{{device.last_heard}}
</div>
</div>
</md-card-content>
</md-card>
Controller:
appControllers.controller('devicesCtrl', function ($scope,$state,$stateParams,$timeout,$mdDialog,$ionicHistory,$ionicLoading,particle,pDevices,safeparse) {
//$scope.isAnimated is the variable that use for receive object data from state params.
//For enable/disable row animation.
var debug = true;
$ionicLoading.show({
content: 'Getting Devices',
animation: 'fade-in',
showBackdrop: true,
maxWidth: 200,
showDelay: 0
});
$timeout(function () {
pDevices.getpDevices().then(function(data) {
$scope.p.devices = data;
if (debug) console.log(debug + 'time out got particle.io device list: ', $scope.p.devices);
$scope.isLoading = false;
if (debug) console.log(debug + 'time out complete, hiding ionicLoading: ');
$ionicLoading.hide();
}, function() {
$scope.p.showAlertDialog($event);
$scope.error = 'unable to load devices'
});
}, 2000);
$scope.initialForm = function () {
//$scope.isLoading is the variable that use for check statue of process.
$scope.isLoading = true;
$scope.isAnimated = $stateParams.isAnimated;
};// End initialForm.
$scope.$watch('p.devices', function (newVal, oldVal){
console.log(newVal, oldVal)
});
$scope.p = {
currentDevice: '',
deviceId: particle.setDevice(),
token: particle.setToken(),
devices: [],
getDevices: function () {
pDevices.getpDevices().then(function(deviceList) {
if (debug) console.log(debug + 'getDevices got particle.io device list: ', deviceList);
$scope.p.devices = deviceList.data;
});
},
// Select the current device for particle platform
setDevice: function (deviceId) {
if (deviceId) {
if (debug) console.log(debug + 'setDevice', deviceId);
$scope.p.deviceId = deviceId;
particle.setDevice(deviceId);
$scope.startup();
}
return $scope.p.deviceId;
}
};
showAlertDialog = function ($event) {
$mdDialog.show({
controller: 'DialogController',
templateUrl: 'confirm-dialog.html',
targetEvent: $event,
locals: {
displayOption: {
title: "No Devices Found.",
content: "Unable to load Device List.",
ok: "Confirm"
}
}
}).then(function () {
$scope.dialogResult = "You choose Confirm!"
});
}// End showAlertDialog.
$scope.initialForm();
});// End of controller Device.
And finally the factory being called:
appServices.factory('pDevices', function($http, localstorage) {
root_url = 'https://api.particle.io/v1/'
var getpDevices = function() {
return $http.get(root_url + 'devices').then(function(response){
console.log('pDevices getpDevices: ', response.data);
return response.data;
});
};
return {
getpDevices: getpDevices
};
});
Screenshot of what I get:
Turns out the problem was entirely in my HTML/SASS div tags as well as my object array which was not device but Object. This is working but needing some formatting corrections.
<ion-view cache-view="false" title="Device List">
<!--note list section-->
<ion-content id="device-list-content" class="bg-white">
<md-list>
<md-card class="card-item"
collection-repeat="Object in p.devices"
collection-item-height="136px"
collection-item-width="100%">
<md-divider></md-divider>
<md-card-content>
<div class="card-content">
<h1 class="md-title-device">
<span>
<i class="fa fa-crosshairs" aria-hidden="true"></i> {{Object.name}}
</span>
</h1>
<div class="device-content-detail">
<div ng-show="Object.connected">
<i class="fa fa-wifi" aria-hidden="true"></i>
<i class="fa fa-heartbeat" aria-hidden="true"></i>{{Object.last_ip_address}}
</div>
<div ng-show="!Object.connected">
<i class="fa fa-wifi" aria-hidden="true"></i>
<i class="fa fa-heart-o" aria-hidden="true"></i>{{Object.last_heard}}
</div>
</div>
</div>
</md-card-content>
</md-card>
</md-list>
</ion-content>

Directive is Not Called when the ng-repeat is finished

I want to call the directive when my ng-repeat is finished. I use two controllers with same name. My problem is that when I call the function of controller the function changes the value of the list. And base on that list ng-repeat is work. When ng-repeat is end directive is called that called the END function. But ng-repeat not work as well as directive also not called.
my HTML code is here
> <body ng-app="modules" >
<div class="container" >
<div class="row" ng-controller="mainctl">
<div class="col-sm-1">
<a href="#" ng-click="divide(1)" ><h3>1*1</h3></a>
</div>
<div class="col-sm-1">
<h3>2*2</h3>
</div>
<div class="col-sm-1">
<h3>3*3</h3>
</div>
<div class="col-sm-1">
<h3>4*4</h3>
</div>
<div/>
<div ng-controller="mainctl">
<div ng-repeat="rows in cells" > <!-- repeat fot rows -->
<div class="row">
<div ng-repeat="cols in cells" repeat-end="onEnd()"> <!-- repeat for colums -->
<div id="Div_{{rows}}{{cols}}" class="col-sm-2 rcorners2">
<center><h1>{{rows}}{{cols}}</h1></center>
<div id="divPictureBoxPlayback{{rows}}{{cols}}" class="pictureboxPlayback'"
ad-drop="true"
ad-drop-end="onDrop($data, $dragElement, $dropElement, $event);" >
<div id="divHeaderPictureBoxPlayback{{rows}}{{cols}}" class="panel panel-default margin-b-0 text-center pictureboxHeader row"
ng-hide="StartPlayerPlayback{{rows}}{{cols}}" >
<div class="">
<span class="col-lg-3 col-xs-3 col-md-3 text-left">{{cameraNamePlayback00}}</span>
<span class="col-lg-9 col-xs-9 col-md-9 text-right pad-0">
<button class="margin-r-10 btn btn-xs" ng-click="StopStreaming('{{rows}}{{cols}}')"><i class="fa fa-close"></i></button>
</span>
</div>
</div>
<div id="divStreamingAreaPlayback{{rows}}{{cols}}" class="video-cointainer text-center row" ng-hide="StartPlayerPlayback{{rows}}{{cols}}"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
here is my controller
app.controller('mainctl', function ($scope,$timeout) {
$scope.cells =["0"];
//Scopes.store('mainctl', $scope);
$scope.divide = function (ar)
{
$scope.value = ar;
$scope.cells = [];
for (var i = 0; i < ar; i++)
{
$scope.cells.push(i + "");
}
}
$scope.divide1=function()
{
for(var i=0;i<$scope.value;i++)
{
for(var j=0;j<$scope.value ;j++)
{
$scope.index=""+i+j;
$("#divPictureBoxPlayback" + $scope.index).attr('class', 'picturebox pictureboxPlayback' + i + j);
$("#divPictureBoxPlayback" + index).show();
}
}
}
$scope.onEnd = function(){
$timeout(function(){
alert('all done');
$scope.divide1();
}, 1);
}
});
here is my directive
app.directive("repeatEnd", function($timeout){
return {
restrict: "A",
link: function (scope, element, attrs) {
if (scope.$last) {
alert("last element ");
scope.$eval(attrs.repeatEnd);
}
}
};
})
It seems you are missing timeout. You will need timeout in your code in directive:
app.directive("repeatEnd", function ($timeout) {
return {
restrict: "A",
link: function (scope, element, attrs) {
if (scope.$last) {
$timeout(function () {
alert("last element ");
scope.$eval(attrs.repeatEnd);
});
}
}
};
})
$timeout will ensure it is executed only when ng-repeat finishes its rendering. The reason for using $timeout over setTimeout is because it will call $apply internally.

Adding html to UI bootsrap popover inside directive

I am an angular beginner and I wish to add an html button inside a popover that I am creating within a directive. Specifically, my directive allows the user to highlight text on the page and a popover will then appear around the selected text. It works for plain text content in the popover but not html. This is the directive as it is now
app.directive('replybox', function ($timeout, $window, $compile, $sce) {
var linkFn = function (scope, element, attrs) {
var exampleText= element.find('p');
var btn = element.find('button');
var windowSelection="";
exampleText.bind("mouseup", function () {
scope.sel = window.getSelection().toString();
windowSelection=window.getSelection().getRangeAt(0);
if(scope.sel.length>0) {
scope.showModal = true;
scope.$apply();
}
});
btn.bind("click", function () {
range = windowSelection;
var replaceText = range.toString();
range.deleteContents();
var div = document.createElement("div");
scope.pophtml = $sce.trustAsHtml("<p>hello world</p> <button>x</button>");
div.innerHTML = '<poper>' + replaceText + '</poper>';
var frag = document.createDocumentFragment(), child;
while ((child = div.firstChild)) {
frag.appendChild(child);
}
$compile(frag)(scope);
range.insertNode(frag);
scope.selection="None";
});
};
return {
link: linkFn,
restrict: 'A',
scope: {
entities: '=',
selection:'='
},
template: `<ng-transclude></ng-transclude>
<div class="modal fade in" style="display: block;" role="dialog" ng-show="showModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
{{sel}}
</div>
<div class="radio">
<div ng-repeat="x in entities">
<div class="radio">
<label>
<input type="radio" name="choice" ng-model="$parent.selection" ng-value = "x">
{{x}}
</label>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" ng-click="showModal=false">
Ok
</button>
</div>
</div>
</div>
</div>`,
transclude: true
};
});
The part that is not working is this part
scope.pophtml = $sce.trustAsHtml("<p>hello world</p> <button>x</button>");
div.innerHTML = '<poper>' + replaceText + '</poper>';
I have a feeling there is something wrong with the above two lines.

Accessing $scope of another controller - ngDialog in AngularJS

I'm instantiating ngDialog like below;
ngDialog.open({
template: 'mod-details',
className: "ngDialog-theme-large",
showClose: false,
closeByDocument: false,
closeByEscape: false,
controller: ['$scope', function($scope) {
// controller logic
$scope.isValid = true;
$scope.orderItem = orderItem;
$scope.countSelection = function() {
var count = 0;
angular.forEach($scope.modifier.menu_modifier_items, function(item){
count += item.selected ? 1 : 0;
});
console.log(item);
return count;
}
}]
});
I then use $scope.orderItem with ng-repeat like below;
<div ng-repeat="modifier in orderItem.menu_modifier_groups">
<div class="menu--modifiers-group" modifier="modifier">
<div class="group-title" ng-class="{'group-hasError': !isValid}">
<div class="title-s ng-binding" ng-bind="modifier.name"></div>
<div class="clearfix"></div>
<span class="text-muted ptop5" ng-if="modifier.instruction" ng-bind="modifier.instruction"></span>
</div>
<div class="group-items" ng-if="modifier.max_selection_points > 1 || (modifier.max_selection_points == 1 && modifier.min_selection_points == 0)">
<div ng-repeat="item in modifier.menu_modifier_items" class="modifier-item multiple">
<label for="<%modifier.id + '_' + item.id%>" ng-click="modifierClicked(item)">
<input id="<%modifier.id + '_' + item.id%>"
class="checkbox-branded"
type="checkbox"
name="<%item.name%>"
ng-model="item.selected"
ng-class="{'not-available': !item.available}"
title="<%item.name%>"
value="<%item.id%>"
ng-disabled="!item.selected && countSelection() == modifier.max_selection_points"
ng-click="modifierClicked(item)"
ng-change="modifierSelected(item, false)">
<span class="item-name">
<span ng-bind="item.name"></span>
<span ng-bind="priceDelta(modifier, item)"></span>
</span>
</label>
</div>
</div>
</div>
</div>
</div>
I'm not able to access modifier in ng-repeat="modifier in orderItem.menu_modifier_groups" or modifier.menu_modifier_items in ng-repeat="item in modifier.menu_modifier_items" in my countSelection function
I've attached a screenshot of ng-inspector.
$scope.modifier is never created into your controller. Your countSelection function can't know which item of the array is being selected this way. One way you could do, is to pass a reference of the array to your function when calling it. Like this:
countSelection(modifier.menu_modifier_items);
And, on the controller:
$scope.countSelection = function(selection) {
var count = 0;
angular.forEach(selection, function(item){
count += item.selected ? 1 : 0;
console.log(item);
});
return count;
}

Resources