Nested transclude directive renders inner transcluded content in wrong place - javascript

I have a myList directive, which transcludes it's content. The problem occurs when I try and nest a <my-list> element inside another <my-list>.
JS Fiddle: http://jsfiddle.net/fqj5svhn/
The directive:
var MyListDirective = (function () {
function MyListDirective() {
this.restrict = 'E';
this.replace = true;
this.transclude = true;
this.scope = {
myListType: '='
};
this.controller = function () {
this.classes = 'my-class';
};
this.controllerAs = 'myList';
this.bindToController = true;
this.template = '<ul ng-class="myList.classes" ng-transclude></ul>';
}
return MyListDirective;
})();
angular.module('myApp', []).directive('myList', function () {
return new MyListDirective();
});
Example usage of the directive:
<div ng-app="myApp">
<my-list my-list-type="'someType'">
<li>foo</li>
<li>bar</li>
<li>
<my-list my-list-type="'anotherType'">
<li>cats</li>
<li>dogs</li>
</my-list>
</li>
</my-list>
</div>
What gets rendered:
<div ng-app="myApp" class="ng-scope">
<ul ng-class="myList.classes" ng-transclude="" my-list-type="'someType'" class="ng-isolate-scope my-class">
<li class="ng-scope">foo</li>
<li class="ng-scope">bar</li>
<li class="ng-scope">
<ul ng-class="myList.classes" ng-transclude="" my-list-type="'anotherType'" class="ng-isolate-scope my-class">
</ul>
</li>
<li class="ng-scope">cats</li>
<li class="ng-scope">dogs</li>
</ul>
</div>
As you can see the list items from the inner myList appear to be transcluded by the outer myList.
What I want to happen:
<div ng-app="myApp" class="ng-scope">
<ul ng-class="myList.classes" ng-transclude="" my-list-type="'someType'" class="ng-isolate-scope my-class">
<li class="ng-scope">foo</li>
<li class="ng-scope">bar</li>
<li class="ng-scope">
<ul ng-class="myList.classes" ng-transclude="" my-list-type="'anotherType'" class="ng-isolate-scope my-class">
<li class="ng-scope">cats</li>
<li class="ng-scope">dogs</li>
</ul>
</li>
</ul>
</div>
Suggestions?

It is happening because when browser renders the page it expects <li> to be inside <ul>, but it your case it is inside <my-list> which is an invalid markup. All these things happen before Angular bootstraps and runs directives. There is no way you can predict how the browser would interpret your markup when it's invalid, in this particular case it pushes <li>'s out to be together.
In this fiddle I've replaced <ul> and <li> with <div>, which does not have any requirements for nesting, and transclusion works just fine.

Related

Is this bug for using AngularJS to fetch data to <li><a href> or not?

I use the AngularJs to fetch the data from mySql database for my navigation bar on HTML5. The problem is I cannot open the link in the sub menu.
Here is my code :
<div id="header-wrapper" class="wrapper">
<div ng-app="myApp" ng-controller="customersCtrl" id="header">
<div id="logo">
<h1>Why Choose a Breeder ?</h1>
<p>Quality Quarantee Knowledge</p>
</div>
<nav id="nav">
<ul>
<li class="current">Home</li>
<li>Holland Lops
<ul>
<li>Bucks</li>
<li>Does</li>
<li>Junior</li>
</ul>
</li>
<li>For Sale</li>
<li>Article
<ul><li ng-repeat="menu in menues">{{menu.Title}}</li></ul>
</li>
<li>Contact us</li>
</ul>
</nav>
</div>
However I cannot open the link in this code (When I click on link, nothing happens):
<ul><li ng-repeat="menu in menues">{{menu.Title}}</li></ul>
But If I remove the ul like this :
<li>For Sale</li>
<li>Article</li>
<li ng-repeat="menu in menues">{{menu.Title}}</li>
I can open the link. I don't know what's wrong. Is it because the order of the navigation bar ? Could you please suggest me, what I'm wrong ?
This is my .js code :
var app = angular.module('myApp', []);
app.controller('customersCtrl', ['$scope','$http',function($scope, $http){
$scope.menues = [];
$http.get("http://www.rhosgobelrabbit.com/getUrl.php")
.then(function (data) {$scope.menues = data.data.records;
}, function (error) {
alert('Error');
});
}]);
You need to use ng-href instead of href. You can read about this in the angularJS docs: Docs
<ul><li ng-repeat="menu in menues"><a ng-href="{{menu.Link}}" target="_self">{{menu.Title}}</a></li></ul>
As long as the ng- aren't placed infront of the href will angular just give you a 404.

ng-class is messing up with static and dynamic content

I have introduced ng-repeat where static contents are already there. Its working properly. When i put ng-class and set the variable its not working. How to fix that issue and why its happening.
Click on each li. Its not working on dynamic elements.
Please find the code in fiddle.
<h3>FIFA Mactch Summary:</h3>
<div ng-app ng-controller="MyCtrl">
<ul>
<li ng-class='{"selectedClass":classHilight==1}' ng-click="filterNews(3);classHilight=1"> My static content 1</li>
<li ng-class='{"selectedClass":classHilight==2}' ng-click="filterNews(3);classHilight=2" > My static content 2</li>
<li ng-class='{"selectedClass":classHilight==3}' ng-click="filterNews(3);classHilight=3"> My static content 3</li>
<li ng-repeat="item in items" ng-class='{"selectedClass":classHilight==item.id}' ng-click="filterNews(item.id);classHilight=item.id" >My Dynamic Content {{item.id}}</li>
</ul>
http://jsfiddle.net/gowthambsvg/2m41tjq9/
It is said that, You must always have . in your model.
In ng-repeat classHilgiht doesn't refer to the scope variable classHilight. It creates its own scope for each item in ng-repeat. It does not refer to classHilight. But when classHilight is used as key of test object, object inherits the property from the child scope of the ng-repeat directive.
Try this:
var m = [{
id: 4
}, {
id: 5
}, {
id: 6
}];
function MyCtrl($scope) {
$scope.test = {};
$scope.items = m;
$scope.setClass = function() {
}
}
.selectedClass {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<h3>FIFA Mactch Summary:</h3>
<div ng-app ng-controller="MyCtrl">
<ul>
<li ng-class='{"selectedClass":test.classHilight==1}' ng-click="test.classHilight=1">My static content 1</li>
<li ng-class='{"selectedClass":test.classHilight==2}' ng-click="test.classHilight=2">My static content 2</li>
<li ng-class='{"selectedClass":test.classHilight==3}' ng-click="test.classHilight=3">My static content 3</li>
<li ng-repeat="item in items" ng-class='{"selectedClass":test.classHilight==item.id}' ng-click="test.classHilight=item.id">My Dynamic Content {{item.id}}</li>
</ul>
</div>
Fiddle here
Edit: One can not say classHilight is not updated in ng-repeat, it is being updated but within its own scope. [Ref]

jQuery function in directive not working

My jQuery function isn't working inside my directive.
This is my directive:
app.directive('responsiveNav', function () {
return {
restrict: 'E',
link: function (element) {
var pull = $('#pull');
var menu = $('.nav-bar ul ul');
var menuHeight = menu.height();
$(pull).on('click', function (e) {
e.preventDefault();
menu.slideToggle();
});
$(window).resize(function () {
var w = $(window).width();
if (w > 320 && menu.is(':hidden')) {
menu.removeAttr('style');
}
});
}
};
});
HTML:
<div class="header" responsive-nav>
<div class="nav-bar">
<ul style="padding:15 0 15 0;height:50px;">
<li style="border-right: none;">
<img src="assets/images/who-logo.png">
</li>
Menu
<ul style="float:right;list-style-type:none;padding:8.5 0 8.5 0;">
<li><a class="active" href="">Home</a></li>
<li>About us</li>
<li>Tickets</li>
<li>Event</li>
<li>Gallery</li>
<li>Video</li>
<li>Contact</li>
<li style="border-right: none;"><a><i class="fa fa-facebook" style="font-size: 1.5em;"></i></a></li>
<li style="border-right: none;"><a><i class="fa fa-instagram" style="font-size: 1.5em;"></i></a></li>
<li style="border-right: none;"><a><i class="fa fa-twitter" style="font-size: 1.5em;"></i></a></li>
</ul>
</ul>
</div>
</div>
The directive doesn't even react to the click on #pull and I have no errors in my console. Hope you understand the problem. Any help is welcome!
Your directive is restricted to Element by
restrict: 'E'
But you have put the directive as an attribute.
<div class="header" responsive-nav>
restrict: 'A' is one way to solve the problem.
Also I don't agree some of the ways you are using jquery here. Try to be angular as much as possible.
Please take some time to refer the angular directive documentation to make better use of this powerful feature of the framework.

ng-click doesn't work on anchor element

Q1: I tried to use nav in bootstrap to make a navigation bar and bound ng-click to the anchors.
However after I click the anchor link,there is nothing happened.
Q2: I've noticed that the anchor link clicked won't be active by setting bg-color to it? How can this be implemented?
Here is the JSfiddle...
<div ng-controller="SuiteSectionCtrl">
<ul class="nav nav-pills nav-stacked">
<li class="active">All Suites
</li>
<li><a ng-click="handleClick">Suite1</a>
</li>
<li>Suite2
</li>
<li>Suite3
</li>
</ul>
The brackets for function invocation are missing. You should have:
ng-click="handleClick()"
Answering Q2:
Maybe there are smarter solutions, but this one works as well:
angular.module('myApp').controller('MenuCtrl', ['$scope', '$location', '$rootScope',
function ($scope, $location, $rootScope) {
$rootScope.$on('$locationChangeSuccess', function () {
var path = $location.path();
// you may apply logic on the path (group together in case of dropdown-menu e.g.)
$scope.topMenu = path;
});
}
]);
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation"
ng-controller="MenuCtrl">
<div class="container-fluid">
<div class="navbar-header">
<!-- ... -->
</div>
<div class="navbar-collapse collapse" id="navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<li ng-class="{active: topMenu == '/'}">
Home</li>
<li ng-class="{active: topMenu == '/about'}">
About</li>
<!-- more... -->
</ul>
</div>
</div>
</div>
I have Updated your code. Add ng-app directive to your body tag. And In your html change ng-click="handleClick" to ng-click="handleClick()"
<body ng-app="app"><div ng-controller="SuiteSectionCtrl">
<ul class="nav nav-pills nav-stacked">
<li class="active">All Suites
</li>
<li><a ng-click="handleClick()">Suite1</a>
</li>
<li>Suite2
</li>
<li>Suite3
</li>
</ul>
</div></body>
and our JS code is
var executionAPP = angular.module('app',[])//register your app
executionAPP.controller('SuiteSectionCtrl',['$scope',function($scope){
$scope.oneAtATime = true;
$scope.testSuites = [{title:"TestSuite1",content:"TestContent1"},
{title:"TestSuite2",content:"TestContent2"},
{title:"TestSuite3",content:"TestContent3"},
{title:"TestSuite4",content:"TestContent4"},
{title:"TestSuite5",content:"TestContent5"}];
$scope.handleClick = function(){
alert('Accordion clicked');
};
}]);
Updated Fiddle...

Getting Dynamic id (from AngularJS) in getElementByID

I have a clickable drop-down List as following:
<ul class="dropdown">
<li ng-repeat="item in items" ng-controller="ListCtrl">
{{item.name}}
</li>
</ul>
I have following code of AngularJS in same html page :
<li ng-repeat="item in items" ng-controller="ListCtrl">
<div id="{{item.itemIndex}}">
Some Code Here
</div>
</li>
Now i want to add each div in to my page when click on the list item every time. I calling addWidget() function like this :
<script type="text/javascript">
function addWidget(){
document.getElementById('').style.display='block';
}
</script>
Now My question is if i assign a static id to div and passing it in to getElementByID then it works fine but in the dynamic case how i pass the id so it will work fine in each case ?
You don't want to be adding javascript like that.
Here is an example of how to do this:
<body ng-app="myApp">
<div ng-controller="ListCtrl">
<ul class="dropdown">
<li ng-repeat="item in items">
{{item.name}}
</li>
</ul>
<ul>
<li ng-repeat="item in items" ng-show="item.show">
<div>Some Code Here</div>
</li>
</ul>
</div>
</body>
And your controller:
function ListCtrl($scope){
$scope.items = [{name: 'one'}, {name: 'two'}];
$scope.addWidget = function(item){
item.show = !item.show;
};
};
And finally a working example is here on jsfiddle

Categories

Resources