AngularJS $location.search() not working - javascript

It's the first time I'm trying to use the $location service in AngularJS in order to check for query string arguments. I've been reading the docs and trying to play a bit with it in Plunkr to see how to use it, but so far I've failed to get it to retrieve any parameters from the query string.
I've been testing it using this plunk http://plnkr.co/edit/RIFdWa5ay2gmRa6Zw4gm?p=info
var app = angular.module('myApp', [])
.config(function($locationProvider) {
$locationProvider.html5Mode(true);
});
angular.module('myApp').controller('myCtrl', function($scope, $location){
$scope.name = "Andrei";
$scope.url = $location.host();
$scope.path = $location.path();
$scope._params = $location.search();
});
I've read that setting html5Mode(true) on the $locationProvider is required in order to get the $location service to work as "expected" - which I've done, but when setting this nothing works anymore in my plunk (you can set it to false and you'll see the binding are qorking again properly).
Am I missing something regarding the $location service?
Any help or suggestions are appreciated!
Thanks!

In AngualarJS 1.3 $location in HTML5 mode requires a <base> tag to be present so that it knows the path that all of the links are relative to. You can add <base href="/" /> to get it working again.
http://plnkr.co/edit/j9rd1PajNLQVJ8r4c8BZ?p=preview

Related

How to get url parameter in angularjs?

I have been trying to get the url parameter in Angular, but this is not a Single Page application. I tried the below code snippet.
www.example.com?param1=ABC
Injected $location in controller, then
var paramValue= $location.search().param1;
In the above case, paramValue is undefined. But, If I change the url to
www.example.com#?param1=ABC (Added # in the URL) it works.
But, I don't want to do this because it breaks the page since it is not SPA.
Can someone suggest a better way to get the url parameter without using # in the url?
try this..
inject $stateParams into the contoller
var paramValue=$stateParams.param1
this will work in your scenario
Use this if you are not using stateParams:
this.$routerOnActivate = function(next) {
$scope.paramValue= next.params.param1;
};
First enable the html5 mode:
Add the following code in router:
app.config(["$locationProvider", function($locationProvider) {
$locationProvider.html5Mode(true);
}]);
Second, Then update the index.html
<head>
...
<base href="/">
</head>
Finally, Inject the $stateParams into the contoller and access using
following
var paramValue=$stateParams.param1
use $routeParams
In AngularJs in your $routeProvider
.when('/sample/:id',
{
templateUrl: 'sample.html',
controller: 'sampleController'
})
In your controller get it with $routeParams.id

Change URL hash while scrolling

I've seen some jQuery plugins for this, but I was wondering if anybody did a service or a directive that does this. Google isn't helping.
Basically, what I'd like is for the URL to update every time I go over an element with (say, a directive and) an id so that if I go to another part of the application and click back I'm returned to the header that I was reading.
Use $anchorScroll and $location
These too services should give you the desired result.
The $location service allows you to change and get the # in the url
Where as the $anchorScroll lets you pin point places in the DOC.
here is a plunker demo
And here is the main controller
angular.module('anchorScrollExample', [])
.controller('ScrollController', ['$scope', '$location', '$anchorScroll',
function ($scope, $location, $anchorScroll) {
$scope.gotoBottom = function() {
// set the location.hash to the id of
// the element you wish to scroll to.
$location.hash('bottom');
// call $anchorScroll()
$anchorScroll();
};
}]);
})(window.angular);
Best of luck

Can't load individual local with ng-src - Angularjs

I ran into a problem while trying to bind a single image to a template. I've typically used repeaters when other data was present. However, here I only need to place one image and no other data. I successfully used ng-repeat in example one to call a image from online. However, a local link produces a broken image. What am I missing here?
FYI. I'm using angular seed project so the controllers are set in app.js and don't need to wrap ng-src.
EXAMPLE 1 - Success
<img ng-src="{{image}}"/>
.controller('someCtrl', ['$scope', function($scope) {
$scope.image = 'https://farm4.staticflickr.com/3261/2801924702_ffbdeda927_d.jpg';
}])
EXAMPLE 2 - Fail
<img ng-src="../img/{{image}}"/>
.controller('someCtrl', ['$scope', function($scope) {
$scope.image = 'cat.jpg';
}])
From a syntax point of view that is correct. I just did this in an angular project I'm working on. Make sure the image is where it is supposed to be and that your relative path is correct. That's about all that can be wrong here. I don't think this is an angular issue.
It should work. Check your picture exists.
http://jsfiddle.net/s0w6eyna/
HTML
<img ng-src="https://farm4.staticflickr.com/3261/2801924702_{{image}}" />
JS
function ImageCtrl($scope) {
$scope.image = 'ffbdeda927_d.jpg';
}

Angularjs - dynamic pages, same template, how to access and load article by id

I am slightly puzzled on how to use angularjs to build a blog-like web site.
If you think of an ordinary blog,,, and say,, I am building it using php and mysql.. what I don't understand is how do I make angular get an article based on id..
I can load data for a list of all articles.. I can load data for a single page (from a static json),, I understand how to send http requests,, but how do I access
mysite.com/page?id=1 or
mysite.com/page?id=2 or
mysite.com/page?id=3
Obviously, I want to load the same template for each separate blog post.. but I have not yet seen a single example that explains this simply.
If I have three posts in my database with id 1,2,3 how is angular meant to generate links to each individual article? I understand that I can load data to assemble urls but what urls? I suppose I am confused with routing.
Could you recommend a SIMPLE and understandable example of this? Could you suggest how to think about this?
Thanks!
In this short explanation I will use examples based on official tutorial.
Propably somwhere in your application you created controllers module with code close to that:
var blogControllers = angular.module('blogControllers', []);
// other controllers etc.
blogControllers.controller('BlogPostCtrl', ['$scope',
// more and more of controller code
We will be back here in a moment :) If you have controllers module, you can create a route linked to the specific controller:
var blogApp = angular.module('blogApp', [
'ngRoute',
'blogControllers'
]);
blogApp .config(['$routeProvider',
function($routeProvider) {
$routeProvider.
// other routes
when('/post/:postId', {
templateUrl: 'partials/blog-post.html',
controller: 'BlogPostCtrl'
}).
// other...
}]);
Well but what we can do with this :postId parameter? Lets go back to our controller:
blogControllers.controller('BlogPostCtrl', ['$scope', '$routeParams', 'BlogPost',
function($scope, $routeParams, BlogPost) {
$scope.post = BlogPost.get({postId: $routeParams.postId});
}]);
As you see, we are passing $routeParams here and then our BlogPost resource (it will be explained). Simplifying (again), in $routeParams you have all the params that you put in the $routeProvider for exact route (so :postId in our example). We got the id, now the magic happens ;)
First you need to add services and/or factories to your app (and look, we are using ngResource):
var blogServices = angular.module('blogServices ', ['ngResource']);
blogServices.factory('BlogPost', ['$resource',
function($resource){
return $resource('action/to/get/:postId.json', {}, {
query: {method:'GET', params: { postId: 'all' }, isArray:true}
});
}]);
Now you know what is our BlogPost in controller :) As you see default value for postId is "all" and yes, our api should retrieve all posts for postId = "all". Of course you can do this in your own way and separate this to two factories, one for details and one for list/index.
How to print all of the blog names? Quite simple. Add list routing without any special params. You already know how to do this so let's skip it and continue with our list controller:
blogControllers.controller('BlogListCtrl', ['$scope', 'BlogPost',
function($scope, BlogPost) {
$scope.blogPosts = BlogPost.query(); // no params, so we are taking all posts
}]);
Voila! All posts in our $scope variable! Thanks to this, they are accessible in the template/view :) Now we just need to iterate those posts in our view, for example:
<ul class="blog-posts">
<li ng-repeat="blogPost in blogPosts">
{{blogPost.title}}
</li>
</ul>
And this is it:) I hope you will find AngularJS quite easy now!
Cheers!
I think what you want to use for this is $routeParams. Have a look at this video from egghead.io which explains how to use it:
http://egghead.io/lessons/angularjs-routeparams
It's a good practice to use hash navigation. So your routing should look like this
mysite.com/blog/#!/id=1
mysite.com/blog/#!/id=2

Pass URL to as $routeParam in AngularJS app

How can I pass actual URL (with slashes, commas, etc.) as a $routeParam to AngularJS App?
this will work:
http://paprikka.github.io/le-bat/#/preview/asdadasda
this won't:
http://paprikka.github.io/le-bat/#/preview/http://page.com
neither will this:
http://paprikka.github.io/le-bat/#/preview/http%3A%2F%2Fpage.com
or this:
http://paprikka.github.io/le-bat/#/preview/?url=http%3A%2F%2Fpage.com
Details
AngularJS routing mechanism by its design does not allow to pass strings with slashes as query parameters. I can understand the reasoning behind this decision - we don't want to create a stateless server here.
However, there are still cases when using different separators or regular expressions in routes might be necessary.
I wanted to create an app that takes a url hash string parameter and loads its content to an iframe (link here). Routes are set up in pretty standard way (I'm using Coffeescript, but this snippet does not differ from pure js):
$routeProvider
.when('/preview/:src', {templateUrl: 'partials/preview.html',
controller: 'PreviewCtrl'})
.when('/preview', {templateUrl: 'partials/preview.html',
controller: 'PreviewCtrl'})
Of course, I can load url from hash before AngularJS gets bootstrapped and then pass it to the library, but it would be nice if I could also update current route parameter when changing data in scope - that's why I think it's much better not to avoid AngularJS API.
Using $routeProvider in Angular 1.2, you can pass in a url if it's at the end of the path by adding an asterik to the pattern. The following should work whether or not you URLComponentEncode the url.
The route:
angular.module('angularApp', ['ngRoute'])
.when('/frame/:picture_url*', {
templateUrl: 'views/frame.html',
controller: 'PictureFrame'
});
The controller:
.controller('PictureFrame', function($scope, $routeParams, $sce){
//whitelist the URL
$scope.picture_url = $sce.trustAsResourceUrl($routeParams.picture_url);
});
Then in your template:
<iframe ng-src="{{picture_url}}"></iframe>
Ok, I've managed to find a solution working with current stable version (#1.0.7).
Current way of handling this problem will involve $route-related events, parsing angular-incompatible urls on the fly and handling them via an additional service working in a similar way as $http interception.
You can see working code examples here: http://embed.plnkr.co/fIA2xj/preview
Main steps
pass an angular-incompatible url as usual, eg. go to site.com/url/http://site.com
listen to a $routeChangeStart event and extract correct url parameter for paths beginning with /url/
encode the correct url parameter to an angular-compatible form (in this particular case, I use base64). Don't use encodeURIComponent, because angular will treat as any other url
redirect to another route with your business logic, eg. site.com/parsed-url/BASE64_GOES_HERE
decode the URL in the controller and use it as usual :)
Code
Create angular app module as usual
angular.module('routes',[]).config([
'$routeProvider',
function($routeProvider){
$routeProvider
.when('/test', {templateUrl: 'test.html'})
// This one is important:
// We define a route that will be used internally and handle
// parameters with urls parsed by us via the URLInterceptor service
.when('/parsed-url/:url', {templateUrl: 'url.html', controller:'URLCtrl'})
.when('/', {redirectTo: '/test'})
.otherwise({templateUrl: '404.html'});
}
])
URL Interceptor service (singleton)
.service('URLInterceptor', function($rootScope, $location){
// We listen to $routeChangeStart event and intercept it if
// the path matches our url scheme. In this case, every route
// beginning with /url/ will be caught
$rootScope.$on('$routeChangeStart', function(e, next, current){
// $location.path does change BEFORE actual routing happens,
// so in this case we get parsed new location object
// for free.
// To be hones, a better way of handling this case might be using
// $locationChangeStart event instead, but it would require us to parse urls
// manually.
var path = $location.path();
// check if string begins with '/url/'
var matcher = path.slice(0,5);
var cleanPath = '';
if (matcher === '/url/'){
// Yes it does, yay!
// Remove leading '/url/' to extract the actual parameter
cleanPath = path.slice(5);
// Encode our url to a safe version. We know that encodeURIComponent won't
// work either, so a good choice might be base64.
// I'm using https://code.google.com/p/javascriptbase64/downloads
$location.path('/parsed-url/' + Base64.encode(cleanPath));
// Prevent default event execution. Note that, it won't cancel related $location Events
e.preventDefault();
}
});
return {
decode: Base64.decode,
encode: Base64.encode
}
})
Controllers
// Main application controller
// We instantiate our URLInterceptor service here
.controller('AppCtrl',function($scope, $location, URLInterceptor){
$scope.navigateTo = function (path) {
$location.path('/url/' + path);
}
})
.controller('URLCtrl', function($scope, $routeParams, URLInterceptor){
$scope.url = URLInterceptor.decode($routeParams.url);
});
Two things you should remember:
Although I tried to create a solution as clean as possible, usually passing the data this way to angular isn't considered a good practice, so try not to use it unless you really need to.
You can handle this issue with only one route. I just find it cleaner this way.
I have a solution but I don't know if it will help you. From Angular documention http://docs.angularjs.org/api/ng.$location $location has a function search(search, paramValue)
To pass the parameter:
parameter = encodeURIComponent url
$location.search({ yourURLParameter: parameter }).path('/preview')
To read the parameter:
url = decodeURIComponent $location.search().yourURLParameter
Of course you need to inject $location dependency
I have mixed search params with routes. Your search needs to come before your routes.. specifically for older browsers. I think ie7 blows up if its not url/?search/#/hash
Try this format:
domain.com/?my=params&another=param/#/my/hashes

Categories

Resources