Angular link inside link - angularjs

I would like to have a div with class "dialog" so when user click on that div anywhere expert links inside it redirects him to one page. And "links" inside that div should redirect user to another page. And return on previous page browser button should return him on correct page. I saw some examples on javascript but they doesn't work for angular and I always get second page when return back.
I have following snippet of code.
<div ng-repeat="dialog in dialogs">
<div class="dialog row well well-sm">
<div class="col-xs-8">
...
<a class="msg-heading" href="#!/item/{{ dialog.adv_id }}">
{{ dialog.adv_name }}
</a>
....
</div>
</div>
</div>

Here is one way you could do it by passing the event object as argument of ng-click function and checking event.target
<div class="dialog row well well-sm" ng-click="doRedirect($event)">
Then in controller or directive:
$scope.doRedirect = function(event){
if(!angular.element(event.target).hasClass('msg-heading') ){
/* not the <a> tag so put your redirect code here */
}
}

Related

How to access nested elements in AngularJS

I have a list of items (divs) with a button. When I click on one of this buttons I can access the element using
$event.currentTarget
that returns some thing like
<div ng-click="myFunc()">
<i class="someclass"></i>
<span>bla bla</span>
</div>
how can I access and elements to modify attributes like class?
Don't. Use existing directives like ng-class or ng-if, etc in your html templates.
<div ng-click="clicked = true">
<span ng-class="{'someclass': clicked}">bla bla</span>
</div>
See stackblitz
Although you can get the html dom element and edit it you should only do this as a last option and other angularjs supported methods have failed or are not supported.
template
<div ng-click="myFunc($event)">
<i class="someclass"></i>
<span>bla bla</span>
</div>
controller
$scope.myFunc(event) {
var elem = angluar.element(event.currentTarget);
elem.children(".someclass").removeClass("someclass")
}

Angular toggle class on a different template

In my header.html page I have this button:
<button class="tabs-menu-btn" ng-click="toggle = !toggle" ng-class="{'open' : toggle}">
<div></div>
</button>
And on wrapper.html I have this div:
<div class="tabs-toolbar" ng-class="{'open' : toggle}">
<ul class="tabs">
<li class="tab">
<a ng-click="toggle = !toggle" ui-sref-active="selected" ui-sref="flows"><span>Flows</span></a>
</li>
</ul>
</div>
So when the button is clicked I want to toggle the 'open' class on the button and div - but currently it only works on the button, if i move the 'tabs-toolbar' onto the same html page it works. Does anyone know what I am doing wrong please?
header and wrapper are part of two different scope. So when you click toggle its is changing only the $scope.header.toggle = false
sample Example:
$scope.header.toggle = true
$scope.wrapper.toggle = false // its not getting reflected because, this scope will not get effected with the action
Solution
make both variable as part of same controller or trigger a function which changes both scope

Is ng-if not evaluated or I do not understand about ng-view clearly

Go straight to the code and I will explain more along the question
I have the index.html file like this:
<body class="horizontal-menu">
<!-- Preloader -->
<div id="preloader">
<div id="status"><i class="fa fa-spinner fa-spin"></i></div>
</div>
<div ng-if="isLoading">
<div id="status"><i class="fa fa-spinner fa-spin"></i></div>
</div>
<section>
<div class="contentpanel">
<!-- content goes here... -->
<error-page ng-if="error"></error-page>
<div ng-view ng-if="!isLoading && !error"></div>
</div>
</div><!-- mainpanel -->
</section>
</body>
I want to implement the indicator for my page, you can see the <div id="status"><i class="fa fa-spinner fa-spin"></i></div> as well as ng-if="isLoading" line.
In the login component I have these line of code to change from login view to register view.
$scope.onRegister = function () {
$rootScope.isLoading = true;
$location.path(routes.REGISTER);
}
What I want is when changing the view from login view to register view, the indicator (spinner) is up. After that, in the register component code I have these lines to force the spinner off.
function registerController($scope, $rootScope, $location, $http) {
$rootScope.isLoading = false;
}
But the spinner rounds endlessly.
I tried to read about $viewContentLoaded, and I put these line of code in my application (parent application) as well as the register controller.
$rootScope.$on('$viewContentLoaded', function (event) {
$rootScope.isLoading = false;
})
It still does not help.
Many thanks in advance for helping me solving that issue.
I think this answer might answer your question that explains how ng-if works:
https://stackoverflow.com/a/19177773/5018962
In short:
The ngIf directive removes or recreates a portion of the DOM tree based on an expression. If the expression assigned to ngIf evaluates to a false value then the element is removed from the DOM, otherwise a clone of the element is reinserted into the DOM.

AngularJS - One controller on two sibling DOM elements

I'm trying to do a very simple thing. I'm displaying a list of values with Edit links beside them. Clicking the edit link reveals a form that lets you update the value.
(I've simplified the question so the items just have one field "name". My actual use case has more fields, but is canonically equivalent.)
I've run into something that looks like a bug in Angular, but given my limited experience with it, I'm not so sure. Here's how I'm trying to do it:
<div ng-repeat-start="item in items" ng-controller="ItemCtrl as ctrl" ng-hide="ctrl.isEditing">
<span>Name: {{item.name}}.</span>
<a href='#' ng-click='ctrl.startEditing()'>Edit</a>
</div>
<div ng-repeat-end ng-show="ctrl.isEditing">
<input type='text' ng-model='item.name'/>
<a href='#' ng-click='ctrl.save()'>Save</a>
</div>
My controller looks like this:
app.controller('ItemController', function() {
this.isEditing = false;
this.startEditing = function() { this.isEditing = true; }
this.save = function() { this.isEditing = false; }
});
Clicking on Edit link calls the right controller function, and the first div hides. But the second div does not hide.
When I rearrange the code to look like this (essentially wrapping the two divs with a wrapper element), all is well.
<div ng-repeat="item in items" ng-controller="ItemCtrl as ctrl">
<div ng-hide="ctrl.isEditing">
<span>Name: {{item.name}}.</span>
<a href='#' ng-click='ctrl.startEditing()'>Edit</a>
</div>
<div ng-show="ctrl.isEditing">
<input type='text' ng-model='item.name'/>
<a href='#' ng-click='ctrl.save()'>Save</a>
</div>
</div>
Any idea what is technically wrong with the first version? Note that the <input> boxes do get populated with the right values from item.name.
PS: There's a reason why I'm trying to keep the two divs siblings: in my use case, they are actually implemented as two trs which are supposed to appear right below each other in a table.
It's not a bug from angular but it is quite logical.
<div ng-repeat-start="item in items" ng-controller="ItemCtrl as ctrl" ng-hide="ctrl.isEditing">
<span>Name: {{item.name}}.</span>
<a href='#' ng-click='ctrl.startEditing()'>Edit</a>
</div>
<div ng-repeat-end ng-show="ctrl.isEditing">
<input type='text' ng-model='item.name'/>
<a href='#' ng-click='ctrl.save()'>Save</a>
</div>
If you see the above code you have injected controller only to the first div so obviously sibling div doesn't know what is ctrl or ItemCtrl until and unless you do as in you second way.
So if you want to achieve it as sibling, if you are using routing then add the controller attribute in your route path.
So that the controller will be active for that entire template and you can achieve what you want.
Hope it helps.
Thats because controller has its own scope. When you placed controller ONLY on your first div controllers' scope is limited to only this one div. When you wrapped both your divs inside another and place controller on wrapper, controllers' scope now is all that inside this wrapper. So in this case this works fine and this is not the angular bug

toggle extra detail for a record inside an ngRepeat

I'm working on a project where the client has supplied a pile of html where I need to plugin the data from our database and have hit a problem that I'm finding difficult to solve....
So first problem is with routing
<div ng-repeat="class in vm.classes">
<div class="class-overview">
<a href="#">
<span class="class-title">{{class.description}}</span>
... more stuff here
</a>
</div>
<div class="class-information collapse">
<div class="full-width">
{{class.longDescription}}
</div>
</div>
</div>
he has supplied some javascript to handle the click on class-overview
$('.class-overview a').on('click',function(e) {
e.preventDefault();
});
$('.class-overview').on('click',function() {
$('.class-overview.active').removeClass('active').next('.class-information').collapse('hide');
$(this).addClass('active').next('.class-information').collapse('show');//.css('top',offset).collapse('show');
});
and i have a line like this in my state provider
// default route
$urlrouterProvider.otherwise("/")
So the problem is that the ui-router handles the click and sends me back to the home page.
The ideal solution is to leave as much of his markup intact, so can anyone tell me how I stop ui-router handling the click?
or failing that, how I might use ng-click and ng-show to get the same effect, i.e. hiding and showing the class-information div...
If I understand well your question, you want to display the .class-information div when you click on the .class-overview element.
That can be done by using a variable in a ng-show like this:
<div ng-repeat="class in vm.classes">
<div class="class-overview">
<a href="#" ng-click="display = !display">
<span class="class-title">{{class.description}}</span>
... more stuff here
</a>
</div>
<div class="class-information" ng-show="display">
<div class="full-width">
{{class.longDescription}}
</div>
</div>
</div>
The display variable will be falsy when you land on the page, therefore the ng-click will be executed, this variable will be set to true.
I see that you are using a collapse class to hide the content if it is collapsed. Then you could use angular ng-class to put the collapse class when the display variable is false. Your div.class-information would look like this:
<div class="class-information" ng-class="{collapse: !display}">
<div class="full-width">
{{class.longDescription}}
</div>
</div>

Resources