Angular: Using $location.path() instead of href - javascript

I recently began using $location.path() within ng-click functions rather than simply referencing a path within the href of an a tag.
My reasons for doing so:
Preference to have ALL logic, including paths navigated to moved out of my views (this may be a bit extreme).
For rare instances where multiple html templates reference the same controller I can change $location.path() once rather than having to remember to update corresponding href's within each template.
So instead of:
<a class="button button-balanced" href="/signup">Sign up</a>
I have:
<button class="button button-balanced" ng-click="goToSignup()">Sign up</button>
and in my controller:
$scope.goToSignup = function() {
$location.path('/signup');
}
My question is, are there drawbacks to setting my Angular app up this way? (note: I'm mainly building Ionic hybrid mobile apps)

Preference to have ALL logic, including paths navigated to moved out of my views (this may be a bit extreme).
You can do with your all logic and paths navigated by using same link button
<a href="/signup" class="button button-balanced" ng-click="SignUpFunc()>Sign Up</a>
the a tag is first execute the click function, then execute the href call. So you can do it by link button.
For rare instances where multiple html templates reference the same controller I can change $location.path() once rather than having to remember to update corresponding href's within each template.
If you using menu option, you can use link button
but if you navigate one controller to another controller, then you should use the
$location.path('/signup');

I also used similar logic in my project.It works fine for me.
<button class="button" ng-click="go('view')">Next Page</button>
$scope.go = function ( path ) {
$location.path( path );
};

Related

jQuery selectors not working inside AngularJS ng-view directive

If I put this:
<button type="button" class="btn btn-info" data-toggle="tooltip" data-placement="top" title="Tooltip on top">
Tooltip on top
</button>
Inside the index.html file, just between the <body> tags, it works -
I got the tooltip shown as it should be.
But If i put the same thing in a directive of ng-view - like this:
<div ng-view></div>
The button is shown but the tooltip is not get fired.
The ng-view contains another html template file, using the ngRoute module which contains the <button> tag as specified above.
It seems like jQuery cannot select elements that are located inside the AngularJS ng-view directive.
How could this be solved?
jQuery can and does select the button. However, AngularJS's digest loop is likely removing the tooltip content from the DOM. Outside of the element that hosts the AngularJS application, this does not apply (no pun intended). Furthermore tooltips popovers are added asynchronously.
To make AngularJS recognize the change
import $ from 'jquery';
import 'bootstrap';
import angular from 'angular';
run.$inject = ["$scope"];
function run($scope) {
const tooltippedElements = $('[data-toggle="tooltip"]');
tooltippedElements.on('hidden.bs.tooltip', onShownOrHidden);
tooltippedElements.on('shown.bs.tooltip', onShownOrHidden);
function onShownOrHidden() {
if (!$scope.$phase()) {
$scope.$apply();
}
}
}
angular
.module('app', [])
.run(run);
But instead of going through all of thirs trouble, use
angular-ui-bootstrap or something similar.
I have found the answer:
jQuery selectors, like $('[data-toggle="tooltip"]').tooltip(); are getting actioned before ng-view is getting actioned.
Therefore tooltip selector is trying to select an element which is not already been loaded to the DOM.
The solution for this problem, is simple:
Include jQuery before AngularJS scripts in the index.html file (at the end of the body tag).
Add ng-if directive to each jQuery script that has selectors (but not to the main jQuery file), like this:
<script src="assets/js/scripts.rtl.js" ng-if="initSrc"></script>
Set $rootScope.initSrc=true after any directive/component is loaded.
All of the jQuery functions will be working properly.

difference between using ui-sref and href(where to use) in ionic framework using ui-router service

I am working on ionic framework. So I am confused with using ui-sref and href. For example for tabs we use ui-sref as we can have various states all linked to some main (base) url.
eg
.state('dashboard', {
url: "/dashboard",
templateUrl: 'templates/dashboard.html',
controller: 'dashboardCtrl'
})
.state('dashboard.active', {
url: '/active',
views: {
'active': {
templateUrl: 'templates/active.html',
controller: 'ActiveCtrl'
}
}
})
My dashboard page has tabs whish have various various states now if I want to move to a diffrent template from one of these states or templates (eg to active.html)
eg.
//active.html
<li class="item">
<a class="button button-positive" ui-sref="dashboard.editClaim"> Edit Claim
</a>
</li>
or
<li class="item">
<a class="button button-positive" href="#/dashboard/editClaim"> Edit Claim
</a>
</li>
here should i use ui-sref or href.
Also editclaim template has tabs should i use ui-sref there and will it work fine because currently that is the problem.
So I am wondering if I have to maintain some state till there. Thank you.
here should i use ui-sref or href.
From docs: https://github.com/angular-ui/ui-router/wiki/Quick-Reference#ui-sref
A directive that binds a link ( tag) to a state. If the state has
an associated URL, the directive will automatically generate & update
the href attribute via the $state.href() method. Clicking the link
will trigger a state transition with optional parameters. Also
middle-clicking, right-clicking, and ctrl-clicking on the link will be
handled natively by the browser.
<a ui-sref="home">Home</a> is converted to:
Home
Use ui-sref if you decided to use ui-router. This is a best practice. You can change in your code associated URL for the same state and you don't need to maintain your links.
Developers rarely use href for example in big lists for better performance to avoid additional watchers, but hope its not your case
<a class="button button-positive" ui-sref="dashboard.editClaim"> Edit Claim
</a>
is going to get convert in:
<a class="button button-positive" href="#/dashboard/editClaim"> Edit Claim
</a>
in your browser since ui-sref is just a simple directive provided by angular. For more info:
https://scotch.io/tutorials/3-simple-tips-for-using-ui-router
What's next? You should use ui-sref when using ui-router

Angularjs convert string to html in view

I am currently trying to add links in my view. I do have links which basically contains html tags as strings.
I tried:
<p data-ng-repeat='i in links' >{$ i.link $}</p>
which basically just deploy in my view : mylink
So I did try:
<p data-ng-repeat='i in links' ><span data-ng-bind-html="i.link"></span></p>
It doesn't work though, any idea how could I achieve this ?
Thanks.
Add the $sce as a dependancy of the module
angular.module('myApp', ['$sce']);
When getting the links
angular.forEach($scope.links, function(value){
value.link = $sce.trustAsHtml(value.link);
});
Using Safe Contextual Escaping (docs.angularjs.org/api/ng/service/$sce) and using trustAs delegate you're telling Angular that this value is safe to use within that context. In this example. $sce.trustAsHtml returns an object that angular can trust is safe to as HTML.
In the first case, you'll actually want to use:
<p data-ng-repeat='i in links' >{{ i.link }}</p>
Double braces, not brace-dollar. In the second case, ng-bind-html will require that you have added "ngSanitize" to your module's dependency list.
angular.module('yourAppNameHere', ['ngSanitize'])
Edit:
If you really do want clickable links on the page, then do pretty much what #sreeramu suggested (Though I'd see if you can't find a way to add a nice description):
<p data-ng-repeat='i in links' ><a ng-href="{{i.link}}">{{i.desc}}</a></p>
(Notice that he suggested using ng-href, instead of href. He's right.)
Insert ngSanitize as a dependency to you app:
angular.module('myApp', ['ngSanitize'])
But before be ensure that you are including the script angular-sanitize.js.
Good luck!
It might be that your links have already got the a tags with it so in this case you do not need to re-add the a tags...
In this case do this...
Add this to you scripts (include acc. to your angular version)
<script type="text/javascript"
src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular-
sanitize.min.js"></script>
Add this to your app.js
var app = angular.module('modulename', [ 'ngSanitize']);
And than in your view do this
If it is the div that you want the link to attach to...
<div ng-bind-html="i.link"></div>
The above would give you something as this
<div><a href='your link'></a></div>

Stop Angular routing links inside ng-view

I'm using Angular JS to dynamically load content like so:
HTML
...
<div ng-controller="MainController">
<div ng-view></div>
</div>
</html>
Angular
(function(){
var app = angular.module('app', ['ngRoute', 'ngAnimate']);
app.config(function($routeProvider) {
$routeProvider.when('/test', {
templateUrl : 'views/test.html',
controller : 'MainController'
});
});
app.controller('MainController', function($scope){ });
})();
This works as expected. However, inside the file test.html I have some links with the href="#" that need to be handled with javascript to do various things. At the moment, Angular is interpreting them with it's routing method and treats them as links to the homepage. How do I stop this and treat the links the way I want?
Example test.html content:
Left
Right
<p>Test content</p>
In a JS file separate from Angular I tried:
$('.slideLeft').on('click',function(){
return false;
});
But it doesn't do the return false, it uses the Angular routing.
You should be using Angular for all your bindings including event bindings. Don't use .on('click'), use ng-click (or .bind if you really need it, but you probably don't).
You can also see from the docs that the <a> directive does nothing if href is empty. Use href="" rather than href="#"
Use href="javascript:void(0)" in anchor attribute and also you should use ngClick instead of binding element using jQuery.

AngularJS - Run directives explicitly

I'm new to AngularJS and I'm struggling with the following issue.
I need to implement a 3 step workflow as follows:
Make a call to a web service that returns a list of strings. For example, ["apple", "banana", "orange"], etc. I intercept the response and add the angle brackets around each of these strings before I send it to the Views.
For each of the string returned by the service, I have to render
<apple />
<banana />
<orange />
Finally, get the actual AngularJS directive corresponding to each of those strings to "execute" (not sure what the right word is) and replace the elements above with the content from the templateUrl property as mentioned in each of their respective directives.
Right now, I'm doing Step 1 and Step 2 above using AngularJS. But I understand that they can be done using plain JavaScript using AJAX calls.
My problem is that the directives don't get "run" or "executed" and I have these tags displayed as plain text on the page -
<apple />
<banana />
<orange />
etc.
How do I tell Angular to replace the custom tags with the actual content from their templates?
Thanks for your help.
UPDATE: Here's what the code looks like:
<div class="content" ng-controller="mainController">
<ul class="feeds">
<li ng-repeat="fruit in fruits">
<div ng-controller="fruitSpecificController"> {{fruit}} </div> <!-- This renders <apple />, <banana />, etc. -->
</li>
</ul>
</div>
Also note that each fruit can have its own controller. In the code above, I say "fruitSpecificController", but ideally that would also be generated at runtime. For example, "appleController", "orangeController", etc. and yes, they'll be child controllers of the parent "mainController".
You can use the compile method, but there is a built in directive that will do this for you - if you are willing to load in via a URL.
ng-include
Using ng-include="'/path/to/template.html'" - the evaluated expression URL will be requested and added to the DOM as a child (compiled for you).
You can also cache the templates using $templateCache (if you want to request multiple templates at the same time or cache it for multiple includes).
That would look something like this:
$templateCache.put(/path/to/template.html, 'apple html string');
custom directive (with $compile)
Otherwise, if you want to load in and compile a string - use a directive inside of a ng-repeat.
.directive('unsafeHtmlCompile', function($compile){
return {
link: function(scope, element, attrs){
scope.$watch(attrs.unsafeHtmlCompile, function(val){
if(val !== undefined){
element.html('');
var el = angular.element(val);
element.append(html);
$compile(el)(scope);
}
});
}
}
}
Remember to remove the watcher, if your data won't change :-)
You probably just need to use the $compile service. The docs aren't super helpful but the gist is that you call $compile, passing in the DOM element (in your case the parent of your directives). That returns a function that you then execute, passing in the scope that you want to use ($rootscope is probably safe).
$compile(element)($rootScope);

Categories

Resources