Unable to bind $scope value to view on Url change - angularjs

I trying to create a search application using angularJS.I am facing the issue in binding $scope values to view when router Url changes.
I have a search field in /main.When I write the query and click on search button, the function does the data fetch and assign to a scope variable.The router URL will change to '/Result' and the respective view is displayed.But the view doesn't have the scope values bound. /main and /Result uses the same controller.
router code in main module :
$routeProvider.
when('/main', {
templateUrl: '/views/search.html',
controller: 'searchCtrl'
}).when('/Result',{
templateUrl:'/views/Result.html',
controller: 'searchCtrl' ,
reloadOnSearch: false
}).otherwise({
redirectTo: '/main'
});
Controller :
On button click from /main
$scope.fetchResult=function(searchWord){
shService.fetchResultDocumentsList(searchWord).data.then(function(response){
//service call here-data fetch is successfull.
$scope.docResultList=response[0];
$scope.docResultList=response[0];
$scope.documents = $scope.docResultList.data.documentEntities;
$location.path('/Result');
}
When the respective view is changing, the binding is not done.But when i replace the $scope.documents with $rootScope.documents binding is successful.
I have read the use of $scope is encouraged over $rootScope.

The controller and $scope gets re initialized when you move from one page to another page. if you want to use $scope , you should consider using service to share the data across controllers.
Create a service, that will hold your variable.
angular.service("dataService", function() {
this.value1 = ""
});
reference that service in your controllers,
angular.controller("myCntrl1", function($scope, dataService) {
$scope.val= dataService.value1 ;
});
angular.controller("myCntrl2", function($scope, dataService) {
$scope.val= dataService.value1 ;
});

As Sajeetharan said, $scope get reinitialized when you update location.
Using angularJs, you don't need to change location. You simply update $scope in the same view you used for searching.
But if you really need to use another view, and assuming your search returns only strings, you could try to pass data through url, and grab it from your controller.
Something like this (not tested):
Solution 1 (Angular way)
Controller
$scope.documents = ""; // init your results to empty/null, as you need
$scope.fetchResult=function(searchWord){
shService.fetchResultDocumentsList(searchWord).data.then(function(response){
//service call here-data fetch is successfull.
$scope.docResultList=response[0];
$scope.docResultList=response[0];
$scope.documents = $scope.docResultList.data.documentEntities;
$location.path('/Result');
}
View
<!-- search div is over here -->
<!-- results goes here -->
<div ng-if="$scope.documents">
{{$scope.documents}}
</div>
Solution 2 (your way)
Router
$routeProvider.
when('/main', {
templateUrl: '/views/search.html',
controller: 'searchCtrl'})
.when('/Result/{data:[a-z]{1,}}',{ //here we specify that data expected format is only lowercase letters
templateUrl:'/views/Result.html',
controller: 'searchCtrl' ,
reloadOnSearch: false
})
.otherwise({
redirectTo: '/main'
});
Controller
// dont forget to inject $stateParams service in your controller
if( !$stateParams.data){
$scope.data = $stateParams.data;
}

Related

angularjs how to handle $stateParams variables after a reload of page

I would like to know how i should keep $stateParams variables after a reload of page.
.state('proSearch', {
url: '/proSearch/:city',
params: {
location: null
},
templateUrl: 'imports/client/ui/proSearch/proSearch.html',
controller: 'proSearchController',
controllerAs: 'vm'
})
When the page is reloaded my controller has lost $stateParams.location data. How can i save it ?
You can save the $stateParams data on a $scope variable instead of a local variable. A $scope variable persists on your scope.
$scope.city = $stateParams.location;
You can access $scope variables on other controllers, as long as you reference $scope.
I guess you don't need to reload the page. Two-way data binding is a cool concept that encourages not having to reload a page to see data update.
you can reach it in the controller with $stateParams service.
function MainController($scope, $stateParams, $state) {
var city = $stateParams.location
state.go($state.current, {location: city}, {reload: true});
}
This code is keep your location params at the city variable and second row is refresh the page with current city parameter. I hope it's help

Override AngularJS route to display template based on $scope variable

Using Angular I have a dozen or so routes setup similar to the following example code.
Is there a way to override which template and controller is loaded based on some other criteria while keeping the URL in tact? My goal is to display a login page when... lets say $scope.isLoggedIn = false. I don't want to change the URL to /login.
SomeApp.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/place', {
templateUrl: 'routes/place.html',
controller: 'PlaceCtrl'
})
.when('/test', {
templateUrl: 'routes/test.html',
controller: 'TestCtrl'
});
}]);
ngRoute is a very simple library that can basically only maps urls to controller/views. If you want more flexibility, try ui-router which has the ability to route based on state.
This isn't really doable with ngRoute, but with ui-router you can dynamically provide different templates based on just about anything you want.
$stateProvider.state('root',
url: '/'
controller: 'HomePageController'
templateProvider: [
'$rootScope'
'$templateCache'
'$http'
($rootScope, $templateCache, $http) ->
templateId = if $rootScope.isLoggedIn then "home-page-logged-in" else "home-page-not-logged-in"
templateId = "/templates/#{templateId}.html"
return $http.get(templateId, cache: $templateCache)
]
)
The catch is, as far as I know, you can't change the controller, only the template. Which kinda stinks.

Angular, UI-Router: How do I get access to both a Ctrl and stateParam values within a template?

Based on these set-ups (Angular UI-Router testing scope inheritance, Angular ui-router - how to access parameters in nested, named view, passed from the parent template?), I did the following (the third holds the relevant issue):
.state("patients", {
url: "/dashboard/patients",
templateUrl: 'patients/index.html',
controller: "patientCtrl"
})
.state("sharedPatients", {
url: "/dashboard/patients/shared",
templateUrl: 'patients/shared_patients.html',
controller: "patientCtrl"
})
.state('showPatient', {
url: "/dashboard/patients/:id",
templateUrl: 'patients/show.html',
controller: ("patientCtrl", ['$scope', '$stateParams', function($scope, $stateParams) {
$scope.patient_id = $stateParams.id;
}])
})
Patients and sharedPatients work without a problem. I can also go to showPatient and access the variable patient_id. However, I cannot access any of the functions or variables established in patientCtrl. Thoughts?
The controller scope inheritance has nothing to do with the state inheritance.
Your controllers only inherit from each other if their views are nested in the DOM.
Also, the syntax you're using there is misleading. controller: ("patientCtrl", [...]) will just ignore that first part. It'll only use the controller inside the array.

AngularJS $location not updated properly when using $routeProvider

I have an Angular JS application with a defaultController which controls the header of the app. Then I have some other controllers one for each view. The views are loaded in the <main>. I load the views using the $routeProvider with this code:
myapp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/login', {
templateUrl: 'templates/login.html',
controller: 'loginController'
}).
when('/dashboard', {
templateUrl: 'templates/dashboard.html',
controller: 'dashboardController'
}).
...
I am trying to display a LOGOUT button inside the header when the loaded view is the dashboard and hide it if the loaded view is the login view. In order to do that I have on the defaultController the $location object and I properly add and remove classes from the LOGOUT button with ng-class.
There is only one problem: $location gives me the correct path the first time I load the page, but after I change the view (changed by the $routeProvider) that variable is not updated anymore, so when I am actually on /#/dashboard , the $location.url is still on /login. Here the controller code:
controllers.controller('defaultController', ['$scope', 'ipCookie', '$location', function($scope, ipCookie, $location) {
$scope.url = $location.url();
...
I also tried with $window.location.hash with the same result.
Any idea?
EDIT: after the accepted answer this is what I ve added on the defaultController in order to make it work
$scope.$on("$locationChangeSuccess", function() {
$scope.url = $location.url();
});
The location is probably updated in the service after your default controller is loaded.
You can either inject the $location service into the scope and make decisions in your template based on it (then it will automatically be watched and re-evaluated) or you could listen for the $locationChangeSuccess event.
When injecting, you can simply $scope.location = $location and then use something like <a ng-hide="location.path() != '/something'">.
$location broadcasts the $locationChangeSuccess on the root scope, so you should be able to listen for it on whichever scope you have available: $scope.$on( "$locationChangeSuccess", function() { /* do something */ } );

AngularJS: Checking if user is on a specific route that uses params

If I have a route as such:
$routeProvider.when('/event/:id', { templateUrl: 'view/event-details.html', controller: 'EventDetailCtrl'});
Is there a way to check if the user is on the /event/:id route
Is using if ($location.path().indexOf('/event/') !== -1) a safe way to check if the user is on this route?
Of course there is. Either you can use a console.log in controller or another way you can use an ng-init in the template URL to call any function. So if the template is loaded then it will call the function and hence you get to know that the user is on that route :)
I'm not sure to fully understand what you want to achieve. Your $routeProvider relays your incoming request to a particular controller. It is inside the controller you can fully access the tokens parsed by your $routeProvider.
Declare $routeParams in your controller to access the tokens of your matched route.
$routeProvider
.when('/event/:id', { templateUrl: 'view/event-details.html', controller: 'EventDetailCtrl'});
In your controller:
.controller('EventDetailCtrl', function($scope, $routeParams) {
$scope.id = $routeParams.id;
})

Resources