angularjs: unable to get data from factory - angularjs

I am unable to get my json data from factory and show it in table.
When I was using the $scope object, it was working fine but then I saw in official website that they don't recommend using $scope anymore. So I am using this parameter as suggested in demo examples. And now my code is not working anymore.
Please see my code and help me in this regard:
HTML:
<body ng-app="admin">
<div ng-controller="controller1 as ctrl1">
<div class="container">
<div class="row">
<div class="col-sm-12">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>IP</th>
<th>Time</th>
<th>No. of times</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="iprow in ctrl1.ipLog">
<td>{{iprow.ip}}</td>
<td>{{iprow.time}}</td>
<td>{{iprow.count}}
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<script src="../framework/angular/angular.min.js"></script>
<script src="javascript/app.js"></script>
<script src="javascript/controllers/profileController.js"></script>
</body>
angular app.js
var admin = angular.module('admin', ['myController']);
admin.factory('simpleFactory', function ($http) {
var ipLog = [];
var factory = {};
factory.getIpLog = function () {
// Simple GET request example:
return $http({method: 'GET', url: 'mysql-query.php'}).
then(function successCallback(response) {
ipLog = response.data;
return ipLog;
}, function errorCallback(response) {
console.log(response.data);
return ipLog;
});
};
return factory;
});
angular profileController.js
var myController = angular.module('myController', []);
myController.controller('controller1', ['simpleFactory', function (factory) {
this.ipLog = [];
init();
function init() {
var myDataPromise = factory.getIpLog();
myDataPromise.then(function (result) {
// this is only run after getData() resolves
this.ipLog = result;
});
}
}]);

Your view:
<body ng-app="admin">
<div ng-controller="controller1">
...
<tr ng-repeat="iprow in ipLog">
...
</body>
factory code:
var admin = angular.module('admin', []);
admin.factory('simpleFactory', function ($http) {
var factory = {};
factory.getIpLog = function () {
// Simple GET request example:
return $http({method: 'GET', url: 'mysql-query.php'});
};
return factory;
});
Grab the factor module inside the controller.
Controller:
var myController = angular.module('myController', ['admin']);
myController.controller('controller1', ['simpleFactory', function (factory) {
$scope.ipLog = [];
function init() {
var myDataPromise = factory.getIpLog();
myDataPromise.then(function (result) {
$scope.ipLog = result.data;
});
}
init();
}]);

in app.js
factory.getIpLog = function () {
// Simple GET request example:
return $http({method: 'GET', url: 'mysql-query.php'});
};
in profileController.js
myController.controller('controller1', ['simpleFactory', function (factory) {
this.ipLog = [];
init();
function init() {
var myDataPromise = factory.getIpLog();
myDataPromise.then(function (success) {
this.ipLog = success;
}, function(error){
console.log(error);
});
}
}]);

In your profileController.js, this in this.ipLog=[] refers to myController but when when you are assigning value to this.ipLog=result, this here doesn't refer to myController. SO your this.ipLog is always an empty array.
try this code:
var myController = angular.module('myController', []);
myController.controller('controller1', ['simpleFactory', function (factory) {
var fixedThis=this;
fixedThis.ipLog = [];
init();
function init() {
var myDataPromise = factory.getIpLog();
myDataPromise.then(function (result) {
// this is only run after getData() resolves
fixedThis.ipLog = result;
});
}
}]);
Please try this code and tell if it works.

Related

How do I get ng-init to work with mutiple functions in a controller?

My html:
<div ng-app="APSApp" class="container">
<br />
<br />
<input type="text" placeholder="Search Terms" />
<br />
<div ng-controller="APSCtl" >
<table class="table">
<tr ng-repeat="r in searchTerms" ng-init="searchTerms=getSearchTerms()" >
<td>{{r.DisplayText}} <input type="text" ng-model="r.SearchInput"></td>
</tr>
</table>
</div>
</div>
<script type="text/javascript">
const moduleId = '#Dnn.ModuleContext.ModuleId';
const tabId = '#Dnn.ModuleContext.TabId';
</script>
<script src="/DesktopModules/RazorCart/Core/Content/Scripts/angular.min.js"></script>
<script src="/DesktopModules/MVC/AdvancedProductSearchMVC/Scripts/AdvancedProductSearch.js"></script>
My angular setup:
var aps = angular.module("APSApp", []);
aps.config(function($httpProvider) {
$httpProvider.defaults.transformRequest = function(data) {
return data !== undefined ? $.param(data) : null;
};
});
aps.factory('SearchTerms',
function($http) {
return {
getSearchTerms: function(onSuccess, onFailure) {
const rvtoken = $("input[name='__RequestVerificationToken']").val();
$http({
method: "post",
url: "/DesktopModules/MVC/AdvancedProductSearchMVC/AdvancedProductSearch/GetAPS",
headers: {
"ModuleId": moduleId,
"TabId": tabId,
"RequestVerificationToken": rvtoken
}
}).success(onSuccess).error(onFailure);
}
};
});
aps.controller('APSCtl',
function(SearchTerms, $scope) {
function getSearchTerms() {
$scope.searchTerms = [];
successFunction = function(data) {
$scope.searchTerms = data;
console.log($scope.searchTerms);
};
failureFunction = function(data) {
console.log('Error' + data);
};
SearchTerms.getSearchTerms(successFunction, failureFunction);
}
function doSomethingElse($scope) {}
});
I'm trying to create a single controller with multiple functions. This works if my angular controller looks like this (and I don't use ng-init):
aps.controller('APSCtl',
function(SearchTerms, $scope) {
$scope.searchTerms = [];
successFunction = function(data) {
$scope.searchTerms = data;
console.log($scope.searchTerms);
};
failureFunction = function(data) {
console.log('Error' + data);
};
SearchTerms.getSearchTerms(successFunction, failureFunction);
});
I was just trying to keep related functions in a single controller. What am I doing wrong? Do I actually have to set up a different controller for each function?
You do not have to assign the value in the template, you can just call the function,
<table class="table" ng-init="getSearchTerms()>
<tr ng-repeat="r in searchTerms" >
<td>{{r.DisplayText}} <input type="text" ng-model="r.SearchInput"></td>
</tr>
</table>
you should have a function named getSearchTerms() in your controller to get it called,
aps.controller('APSCtl',
function(SearchTerms, $scope) {
$scope.getSearchTerms() {
$scope.searchTerms = [];
successFunction = function(data) {
$scope.searchTerms = data;
console.log($scope.searchTerms);
};
failureFunction = function(data) {
console.log('Error' + data);
};
SearchTerms.getSearchTerms(successFunction, failureFunction);
}
function doSomethingElse($scope) {}
});

Updating current list from one controller to another in angularjs?

Im having issues updating a list. I have tried both rootscope and using factory but it just doensn't update the view. Rather it remains the same. The only time the update works is if the list is empty to begin with otherwise the original load is always there. Appreciate any suggestions.
Here is my attempt using rootscope:
rootscope alternative
app.config(['$routeProvider', function($routeProvider){
$routeProvider
.when('/',{
replace:true,
templateUrl: 'views/questions.html',
controller: 'SiteController as vm'
})
.when('/categories',{
templateUrl: 'views/categories.html',
controller: 'CategoriesCtrl as cm'
})
.when('/categories/:name*',{
templateUrl: 'views/questions.html',
controller: 'SiteController as vm'
})
.otherwise({
redirectTo: '/'
})
}]);
index.html
<div class="col-xs-12 col-sm-8 col-md-8" ng-view>
All views load here
</div>
questions.html
<table class="table table-questions">
<thead>
</thead>
<tbody>
<tr dir-paginate-start="q in vm.allquestions>
<td>
<a class="questionlinks" ng-click="vm.viewquestion(q.idquestion)> {{q.question}} </a><h4></h4>{{q.date }}
</td>
<td class="text-center"><span class="box box-blue"> {{q.clicks}} </span></td>
</tr >
</tbody>
</table>
categories.html
<div class="wrapper content content-categories content-tags" id="categories_content">
<h2>Categories</h2>
<div class="col-md-12">
<ul class="list-tags" ng-repeat="c in cm.categories">
<li><a ng-href="#/categories{{c.categoryurl}}" ng-click="cm.getCategoryQuestions(c.idcategory)">{{c.categoryname}}</a></li>
</ul>
</div>
<div class="col-md-12">
<nav>
</nav>
</div>
</div >
Now the controllers
SiteController
(function () {
'use strict';
angular
.module('app')
.controller('SiteController', SiteController);
SiteController.$inject = ['$http','$route','$routeParams','$rootScope'];
function SiteController($http,$route,$routeParams,$rootScope) {
var vm = this;
vm.allquestions=[];
vm.thequestions=thequestions;
init();
function init(){
thequestions();
}
function thequestions() {
var url;
$rootScope.$on('updateQs',function(event, obj){
url=obj;
$http.get(url).then(function (response) {
vm.allquestions=response.data;
});
});
$http.get("/getlatestquestions").then(function (response) {
vm.allquestions=response.data;
});
}
}
})();
Categories Controller
(function () {
'use strict';
angular
.module('app')
.controller('CategoriesCtrl', CategoriesCtrl);
CategoriesCtrl.$inject = ['$http','$rootScope'];
function CategoriesCtrl($http,$rootScope) {
var cm = this;
cm.categories=[];
cm.categoryquestions=[];
//CATEGORIES
cm.getCategories=getCategories;
cm.getCategoryQuestions= getCategoryQuestions;
init();
function init(){
getCategories();
}
//CATEGORIES RELATED
function getCategories() {
var url="/getcategories";
var categoryPromise=$http.get(url);
categoryPromise.then(function (response) {
cm.categories=response.data;
})
}
function getCategoryQuestions(idcategory) {
var url="/getcategoryquestions"+idcategory;
$rootScope.$emit('updateQs',url);
}
}
})();
Factory alternative
Added this in the app.module file under app.config
app.factory("newquestions", function () {
var questions = {};
return {
setQs: function (value) {
questions = value;
},
getQs: function () {
return questions;
}
};
});
This in SiteController
(function () {
'use strict';
angular
.module('app')
.controller('SiteController', SiteController);
SiteController.$inject = ['$http','$route','$routeParams','newquestions'];
function SiteController($http,$route,$routeParams,newquestions) {
var vm = this;
vm.allquestions=[];
vm.thequestions=thequestions;
init();
function init(){
initial();
thequestions();
}
function initial(){
newquestions.setQs("/getlatestquestions");
}
function thequestions() {
var url=newquestions.getQs();
$http.get(url).then(function (response) {
vm.allquestions=response.data;
});
}
}
})();
This in CategoriesController
(function () {
'use strict';
angular
.module('app')
.controller('CategoriesCtrl', CategoriesCtrl);
CategoriesCtrl.$inject = ['$http','newquestions'];
function CategoriesCtrl($http,newquestions) {
var cm = this;
cm.categories=[];
cm.categoryquestions=[];
//CATEGORIES
cm.getCategories=getCategories;
cm.getCategoryQuestions= getCategoryQuestions;
init();
function init(){
getCategories();
}
//CATEGORIES RELATED
function getCategories() {
var url="/getcategories";
var categoryPromise=$http.get(url);
categoryPromise.then(function (response) {
cm.categories=response.data;
})
}
function getCategoryQuestions(idcategory) {
var url="/getcategoryquestions"+idcategory;
newquestions.setQs(url);
}
}
})();
It wouldn't work. There is no way to know either of your controllers to know that list has changed.
Solution
Use event broadcasts.
Broadcast or emit an event from two controllers. And use it as a trigger point.

Why Angular js Service does not work?

I wrote script to test passing variables between controllers, so i define a service and declare variable on it getContents, then pass it to next controller personController, but something goes wrong, this is my script:
<script>
angular.module("app", []).service("personService", function () {
var getContents = {};
})
.controller("personController", function ($http, $scope, personService) {
$scope.GetContents = function () {
$http.get("/Home/Get").success(function (data) {
debugger;
personService.getContents = data;
$scope.Persons = data;
});
}
$scope.Save = function () {
$http.post("AddPerson",$scope.model).success(function (status) {
debugger;
console.log('status =', status);
$scope.ShowForm = false;
$scope.GetContent();
});
}
$scope.AddPerson = function () {
$scope.ShowForm = true;
$scope.model = {};
}
});
</script>
what is wrong?
NOTE: when i remove the Service, the controller work properly and get data from /Home/Get.
Edit: this is my edit:
<script>
angular.module("app", []).service("personService", function () {
var Content = {};
return {
getContent: function () {
return Content;
},
setContent: function (value) {
Content = value;
}
};
})
.controller("personController", function ($http, $scope, personService) {
$scope.GetContents = function () {
debugger;
$http.get("/Home/Get").success(function (data) {
debugger;
console.log("successData :", data); //console did not log
personService.setContent(data);
console.log("ServiceData:",personService.getContent()) //console did not log too
$scope.Persons = data;
});
}
$scope.AddPerson = function () {
$scope.ShowForm = true;
$scope.model = {};
}
});
</script>
and this is my html:(for more help)
<div ng-app="app">
<div class="container" ng-controller="personController" ng-init=" GetContent()">
<div ng-show="!ShowForm">
<table class="table">
<thead>
<tr>
<th>Firstname</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="person in Persons">
<td>{{person.Name}}</td>
</tr>
</tbody>
</table>
</div>
</div>
you have to return service
service
angular.module("app", []).service("personService", function () {
var content = {};
var person = {
setContent :function(item){
content = item;
}
getContent : function(){
return content;
};
};
return person;
})
Controller
.controller("personController", function ($http, $scope, personService) {
$scope.GetContents = function () {
$http.get("/Home/Get").success(function (data) {
debugger;
personService.setContent(data); // set content to service..
$scope.Persons = data;
});
}
$scope.Save = function () {
$http.post("AddPerson",$scope.model).success(function (status) {
debugger;
console.log('status =', status);
$scope.ShowForm = false;
personService.getContent(); // get content from service..
});
}
$scope.AddPerson = function () {
$scope.ShowForm = true;
$scope.model = {};
}
define personService.getContent() to $scope variable to display on view page.
$scope.content = personService.getContent();

Nothing happens when Angular Href is clicked

I am using Angular Routing with a webapi 2 controller.
Although the default path loads with the correct data, when I click on an item in a list containing a link to a details page, no data is loaded.
The browser shows what I believe to be the correct url (http://localhost:xxxxx/#/details/2) but the DetailsController script file is not called and no method on the webapi2 controller is called.
Here is my main page :
<div class="jumbotron">
<h1>Movies Example</h1>
</div>
#section scripts {
<script src="~/Scripts/angular.js"></script>
<script src="~/Scripts/angular-route.js"></script>
<script src="~/Client/Scripts/atTheMovies.js"></script>
<script src="~/Client/Scripts/ListController.js"></script>
<script src="~/Client/Scripts/DetailsController.js"></script>
}
<div ng-app="atTheMovies">
<ng-view></ng-view>
</div>
Here is the list partial :
<div ng-controller="ListController as ctrl">
<h1>{{ctrl.message}}</h1>
<h2>There are {{ctrl.movies.length}} Movies in the Database</h2>
<table>
<tr ng-repeat="movie in ctrl.movies">
<td>{{movie.Title}}</td>
<td>
<a ng-href="/#/details/{{movie.Id}}" >Details</a>
</td>
</tr>
</table>
</div>
Here is the details partial:
<div ng-controller="DetailsController as ctrl2">
<h2>ctrl2.message</h2>
<h2>{{movie.Title}}</h2>
<div>
Released in {{movie.ReleaseYear}}
</div>
<div>
{{movie.Runtime}} minutes long.
</div>
</div>
Here is the javascript file to create the angular app:
(function () {
var app = angular.module("atTheMovies", ["ngRoute"]);
var config = function ($routeProvider) {
$routeProvider
.when("/list", { templateUrl: "/client/views/list.html" })
.when("/details/:id", { templatUrl: "/client/views/details.html" })
.otherwise(
{ redirectTo: "/list" });
};
app.config(config);
}());
Here is the javascript file to create the list controller:
(function (app) {
app.controller("ListController", ['$http', function ($http) {
var ctrl = this;
ctrl.message = "Hello World!";
ctrl.movies = [];
$http.get("/api/movie")
.success(function (data) {
ctrl.movies = data;
})
.error(function(status){
ctrl.message = status;
});
}])
}(angular.module("atTheMovies")));
Here is the javascript file to create the details controller:
(function (app) {
app.controller("DetailsController", ['$routeParams', '$http', function ($routeParams, $http) {
var ctrl2 = this;
ctrl2.message = "";
ctrl2.movie = {};
var id = $routeParams.id;
$http.get("/api/movie/" + id)
.success(function(data){
ctrl2.movie = data;
}).error(function (status) {
ctrl2.message = status;
});
}])
}(angular.module("atTheMovies")));
Finally here is the webapi2 controller
public class MovieController : ApiController
{
private MovieDb db = new MovieDb();
// GET: api/Movie
public IQueryable<Movie> GetMovie()
{
return db.Movies;
}
// GET: api/Movie/5
[ResponseType(typeof(Movie))]
public IHttpActionResult GetMovie(int id)
{
Movie movie = db.Movies.Find(id);
if (movie == null)
{
return NotFound();
}
return Ok(movie);
}
You have a typo in your route config i.e. templatUrl
.when("/details/:id", { templatUrl: "/client/views/details.html" })
should be
.when("/details/:id", { templateUrl: "/client/views/details.html" })

How can I use the exact same array from one service in two controllers?

I have this code:
controller:
function deleteRootCategory(){
$scope.rootCategories[0] = '';
}
function getCategories(){
categoryService.getCategories().then(function(data){
$scope.rootCategories = data[0];
$scope.subCategories = data[1];
$scope.titles = data[2];
});
}
getCategories();
service:
var getCategories = function(){
var deferred = $q.defer();
$http({
method:"GET",
url:"wikiArticles/categories"
}).then(function(result){
deferred.resolve(result);
});
}
return deferred.promise;
}
html:
<div ng-controller="controller">
<div ng-repeat="root in rootCategories"> {{root}} </div>
<div ng-repeat="sub in subCategories"> {{sub}} </div>
<div ng-repeat="title in titles">{{title}}</div>
</div>
html2:
<div ng-controller="controller">
<div ng-include src="html"></div>
<button ng-click="deleteRootCategory()">Del</button>
</div>
When I click the deleteRootCategory-button the array $scope.rootCategories is updated, but the view won't ever change.
What am I missing?
Thanks
You will probably want to have a broadcast event set up when the value is changed in the service. Something like this.
.service("Data", function($http, $rootScope) {
var this_ = this,
data;
$http.get('wikiArticles/categories', function(response) {
this_.set(response.data);
}
this.get = function() {
return data;
}
this.set = function(data_) {
data = data_;
$rootScope.$broadcast('event:data-change');
}
});
Have both controllers waiting for the event, and using the set to make any changes to the array.
$rootScope.$on('event:data-change', function() {
$scope.data = Data.get();
}
$scope.update = function(d) {
Data.set(d);
}

Resources