Can't access $scope variables after changing view with $location.path - angularjs

I'm trying to access data that is on the $scope on a view where the app lands after clicking a button but it seems as if after using $location.path(url) to do the redirection the APP cannot see a variable that exists on the $scope anymore.
Form with the button:
<form ng-submit="getBrokenProbes()">
<table class="table table-striped">
<tr>
<th>Bmonitor</th>
<th>Select Bmonitor</th>
</tr>
<tr ng-repeat="bmonitor in bmonitors">
<td>
<span>{{bmonitor.domainName}}</span>
</td>
<td>
<button class="btn btn-primary" ng-click="getBrokenProbes(bmonitor)">Request</button>
</td>
</tr>
</table>
</form>
Controller:
app.controller('logmeinValidationCtrl', ['$scope','$http', '$location', function($scope,$http, $location){
$scope.bmonitors = {};
$scope.brokenProbes = {};
$http.get('http://localhost/getBmonitors').success(function (data) {
$scope.bmonitors = data;
console.log($scope.bmonitors);
});
$scope.getBrokenProbes = function(bmonitor) {
let url = 'http://localhost/getBrokenProbes';
$http.post(url, bmonitor).then(function (response) {
$scope.brokenProbes = response.data.hosts;
console.log($scope.brokenProbes);
$scope.showBrokenProbes();
})
};
$scope.showBrokenProbes = function () {
$location.path('/logmeinValidationResult')
}
}]);
I'm trying to show that data in a different view but $scope.brokenProbes is not available in logmeinValidationResult.html (the page where I land after $location.path) so it just shows an empty table.
logmeinValidationResult.html
<table class="table table-striped">
<tr>
<th>Probe name</th>
</tr>
<tr ng-repeat="probe in brokenProbes">
<td>
<span>{{probe.description}}</span>
</td>
</tr>
</table>
New page controller:
app.controller('logmeinValidationResultCtrl', ['$scope', function($scope){
console.log($scope.brokenProbes); //This yields undefined
}]);

I) The variable $scope.brokenProbes belongs to the controller logmeinValidationCtrl where is defined...
In order to use it inside another controller, you should pass it - broadcast.
OR
II) Another (Better) solution is when the user gets redirected to logmeinValidationResult, you can call the API, get the data and assign to $scope.brokenProbes variable.
In that case,
your old controller should look like this:
app.controller('logmeinValidationCtrl', ['$scope','$http', '$location', function($scope,$http, $location){
$scope.bmonitors = {};
$http.get('http://localhost/getBmonitors').success(function (data) {
$scope.bmonitors = data;
console.log($scope.bmonitors);
});
$scope.getBrokenProbes = function(bmonitor) {
$location.path('/logmeinValidationResult/' + bmonitor); // Pass bmonitor to the result here so you can call the api with that parameter later on
};
}]);
And your here is how your new page controller should look like:
app.controller('logmeinValidationResultCtrl', ['$scope','$http', '$routeParams', function($scope,$http, $routeParams){
$scope.brokenProbes = [];
let url = 'http://localhost/getBrokenProbes';
let bmonitor = $routeParams.bmonitor; // Get passed bmonitor value from the route params
$http.post(url, bmonitor).then(function (response) {
$scope.brokenProbes = response.data.hosts;
console.log($scope.brokenProbes);
})
}]);
And don't forget to register route param bmonitor to your $routeProvider or whatever you use...

Related

Passing values from controller to controller in AngularJs using Factory

I trying to pass a value from controller1 to controller2 using factory on ng-click, now i have added routing
var app = angular.module("myApp", ['ui.router']);
app.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('ShowData', {
url: '/ShowData',
templateUrl: '../Pages/Show.html'
})
.state('EditData', {
url: '/EditData',
controller:'Editctrl',
templateUrl: '../Pages/Edit.html'
})
});
app.controller('Controller1', function ($scope, $http, Phyfactory) {
//Here I am calling a factory
$scope.open = function (name) {
var message = name;
console.log('Hcpname', message);
Phyfactory.set(message);
$location.url('/EditData');
// this is my second controller
app.controller('Editctrl', function ($scope, Phyfactory) {
alert('cntrl2');
$scope.fks = Phyfactory.get();
});
I want to bind this value to textbox
<div ng-controller="Controller2">
Name: <input type="text" ng-model="fks" />
</div>
//this is my factory
app.factory("Phyfactory", function () {
var phyname = {};
function set(data) {
phyname = data;
alert('Inside set :' + phyname);
}
function get() {
alert('Inside get :' + Object.values(phyname));
return phyname;
}
return {
set: set,get:get
}
})
Adding HTML part for controller1 as requested, i am calling ng-click inside td
<div ng-app="myApp" ng-controller="controller1"
<table class="wtable">
<tr>
<th class="wth">
A
</th>
<th class="wth">
B
</th>
</tr>
<tr ng-repeat="tab in Phyperform | filter:search.view_nm|filter:search.time_period|filter:search.team_nm">
<td class="wtd" ><a ng-click="open(tab.A)"> {{tab.A}} </a> </td>
<td class="wtd"> {{tab.B}} </td>
</tr>
</table>
Value is not passing to controller2 and not redirecting as well.
Any idea?
window.location.href
will redirect to out of the app, you must use routing with $location.
of course a better way to pass data between controllers is using event!
using event like below :
this is event receiver in controller 2:
$scope.$on('myCustomEvent', function (event, data) {
console.log(data); // 'Data to send'
});
and this is the sender event in controller 1:
$scope.$emit('myCustomEvent', 'Data to send');
Credit goes to this post "Sharing Data between pages in AngularJS returning empty"
I able to do using sessionStorage.

Updating model without scope in AngularJS

I have been searching for answers for several hours and I think I need to add a separate question. I have the following table and controller:
<table class="table table-striped">
<thead>
<tr>
<th>value</th>
<th>datapoint</th>
</tr>
</thead>
<tr ng-repeat="obj in cont.objs">
<td>{{ obj.value }}</td>
<td>{{ obj.datapoint }}</td>
</tr>
</table>
<button>Next</button>
objects.controller.js
(function() {
'use strict';
angular
.module('app.objects')
.controller('ObjectsController', ObjectsController );
ObjectsController.$inject = ['objectsService', '$state', '$stateParams', '$uibModal', 'logger'];
function ObjectsController(objectsService, $state, $stateParams, $uibModal, logger) {
var cont = this;
activate().then( function successCallback(selectObjects) {
cont.objects = loadObjects(selectObjects._links.objects.href);
});
}
function loadObjects(uri) {
...
cont.objects = getObjects(uri)
return cont.objects;
}
...
I have a button 'Next' and when pressed, needs to update cont.objects by fetching new cont.objects from the api by calling loadObjects with the original uri + '/2'.
I thought maybe
<button ng-click="cont.loadObjects(cont.objects.next.href)">Next</button>
would work, but I get an error saying loadObjects is undefined. Any ideas?
Hope you had defined activate() function and to make this work use
controller As with the controller definition and make sure you are clicking the button after the success of activate() function .
https://toddmotto.com/digging-into-angulars-controller-as-syntax/
You're not binding that function to scope. You need to add that function inside of your controller and bind it.
function ObjectsController(objectsService, $state, $stateParams, $uibModal, logger) {
var cont = this;
cont.loadObjects = loadObjects;
function loadObjects(uri) {
cont.objects = getObjects(uri)
return cont.objects;
}
activate().then(function successCallback(selectObjects) {
cont.objects = loadObjects(selectObjects._links.objects.href);
});
}

Troubleshoot Angular Views when no error happens

I am beginning to learn Angular, and I am having this issue. I am getting data from a web service using REST, then passing this data to the controller as data.d.results, I check in developer tools and results.length is 11, all is fine. I modified my html to include ng-app,ng-controller. My HTML for the Controller wrapper looks like this:
<table ng-controller="ListsController as vm">
<thead>
<tr>
<td>Image</td>
<td>Product</td>
<td>Code</td>
<td>Available</td>
<td>Price</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="product in vm.products">
<td>
<img ng-src="{{product.ImageUrl.Url}}" title="{{product.Title}}" style="width: 50px;margin:2px;" />
</td>
<td>{{product.Title}}</td>
<td>{{product.ProductCode}}</td>
<td>{{product.ReleaseDate}}</td>
<td>{{product.Price | currency}}</td>
</tr>
</tbody>
</table>
and My controllerJS file looks like this:
(function () {
angular
.module("sitemanagerapp")
.controller("ListsController",
ListsController);
function ListsController() {
var vm = this;
var getProducts = getAllItems('Products');
getProducts
.done(function (data, status, jqXHR) {
vm.products = data.d.results;
})
.fail(function (jqXHR, status, error) {
LogError(error);
});
}
}());
I am checking in developer tools, and at the end, vm.products is populated with the data from the service. But why my table isn't filled with the data? How can I troubleshoot problems related to it? No errors are shown for me or anything.
I suppose your getProducts is not implemented with angular's $http or $resource.
In such case, to achieve your goal, you have to inject $scope into your controller even though you are using controllerAs syntax.
(function () {
angular
.module("sitemanagerapp")
.controller("ListsController",
['$scope', ListsController]);
function ListsController($scope) {
var vm = this;
var getProducts = getAllItems('Products');
getProducts
.done(function (data, status, jqXHR) {
vm.products = data.d.results;
$scope.$apply();
})
.fail(function (jqXHR, status, error) {
LogError(error);
});
}
})();

Change the url without reloading the controller in Angularjs

Initially, I am showing all the users name in the table. Once the user selected any one of the name, I call the LoadData method with the selected user as the parameter. I am changing the url #/Trades/User/User1 and append the details under the User1. My requirement is 1) In the LoadData method, I want to change the url to as #/Trades/User/User1 or #/Trades/User/User2 based on the selection 2) It should update the data and reflect in view, but it should not reload the controller.
HTML
<div ng-app="myApp" ng-controller="myCtrl">
<table>
<tr ng-repeat-start="val in data.Titles" class="h" ng-click="LoadData(val.title)">
<td colspan="2" ng-hide="val.title == undefined">{{val.title}}</td>
</tr>
<tr ng-repeat="con in val.details">
<td>{{con.portfolio}}</td>
<td>{{con.status}}</td>
</tr>
<tr ng-repeat-end>
<td colspan="2">Load More</td>
</tr>
</table>
</div>
Code
angular.module("myApp", [])
.controller("myCtrl", ["$scope", function ($scope) {
$scope.data = {"Titles":[{title:"User 1",
details: [{portfolio: "Microsoft", status:"Active"},{portfolio:"IBM", status:"Inactive"}]
}, {title:"User 2",
details: [{portfolio: "Yahoo", status:"Inactive"},{portfolio: "Google", status:"Active"}]
}]};
$scope.LoadData = function(id) {
Change the url as #/Trades/Author/User1
Load the details of the User1
};
});
You could try this. I am using this currently in my project for something very similar. http://joelsaupe.com/programming/angularjs-change-path-without-reloading/
app.run(['$route', '$rootScope', '$location', function ($route, $rootScope, $location) {
var original = $location.path;
$location.path = function (path, reload) {
if (reload === false) {
var lastRoute = $route.current;
var un = $rootScope.$on('$locationChangeSuccess', function () {
$route.current = lastRoute;
un();
});
}
return original.apply($location, [path]);
};
}])

How to implement Infinite Scrolling for AngularJS & MVC

I created one angular JS application using MVC 4
where i created one view which renders templates in that we have one template which contains large amount of data as one lack records for that i am looking to implement Infinite Scrolling
1.index.cshtml
<div id="sidebar-left" class="span2">
<div class="nav-collapse sidebar-nav">
<ul class="nav nav-tabs nav-stacked main-menu">
<li class="navbar-brand">Talks</li>
<li class="navbar-brand">SRDNames</li>
<li class="navbar-brand">Speakers</li>
<li class="navbar-brand">Add Talk</li>
</ul>
</div>
</div>
SRDNames.cshtml
<div class="box-content">
<table class="table table-striped table-bordered bootstrap-datatable datatable">
<tr>
<th>
SRD_NAME
</th>
<th>
CREATED_BY_USER_ID
</th>
</tr>
<tr ng-repeat="srdname in srdnames">
<td>
{{srdname.sRD_NAME}}
</td>
<td>
{{srdname.cREATED_BY_USER_ID}}
</td>
</tr>
</table>
3.eventModule.js
var eventModule = angular.module("eventModule", []).config(function ($routeProvider, $locationProvider) {
//Path - it should be same as href link
$routeProvider.when('/Events/Talks', { templateUrl: '/Templates/Talk.html', controller: 'eventController' });
$routeProvider.when('/Events/Speakers', { templateUrl: '/Templates/Speaker.html', controller: 'speakerController' });
$routeProvider.when('/Events/AddTalk', { templateUrl: '/Templates/AddTalk.html', controller: 'talkController' });
$routeProvider.when('/Events/SRDNames', { templateUrl: '/Templates/SRDNames.html', controller: 'srdnamescontroller' });
$locationProvider.html5Mode(true);
});
srdnamescontroller.js
eventModule.controller("srdnamescontroller", function ($scope, EventsService) {
EventsService.getSRDName().then(function (srdnames) { $scope.srdnames = srdnames }, function ()
{ alert('error while fetching talks from server') })
});
5.EventsService.js
eventModule.factory("EventsService", function ($http, $q) {
return {
getSRDName: function () {
// Get the deferred object
var deferred = $q.defer();
// Initiates the AJAX call
$http({ method: 'GET', url: '/events/GetSRDName' }).success(deferred.resolve).error(deferred.reject);
// Returns the promise - Contains result once request completes
return deferred.promise;
},
});
looking to implement like http://jsfiddle.net/vojtajina/U7Bz9/ in above application.. please help
Demo
There are many possible solutions. Here is one that may work for you.
Implement a scroll module that defines the following:
An infiniteScroll directive
A data service to get the scrollable data
You can use the scroll module from within your app:
HTML:
<div ng-app="app" ng-controller="ctrl">
<div infinite-scroll="items">
</div>
</div>
JS:
var app = angular.module('app', ['scroll']);
app.controller('ctrl', function($scope, dataService) {
$scope.items = [];
dataService.loadMore($scope.items, function(lastItem) {
var items = [];
var id = lastItem ? lastItem.id : 0;
for (var i = 0; i < 5; i++) {
items.push({id: id + i});
}
return items;
});
});
The dataService exposes a loadMore method that accepts an array, and a callback function to load more data. The above example loads more data by looping through 5 items, and adding to the array. But you can customize this function callback to retrieve data from another service:
var app = angular.module('app', ['scroll']);
app.controller('ctrl', function($scope, $http, dataService) {
$scope.items = [];
dataService.loadMore($scope.items, function(lastItem, done) {
var lastItemId = lastItem ? lastItem.id : '';
$http({ method: 'GET',url:'api/items/' + lastItemId})
.success(function(items) {
done(items);
});
});
});

Resources