I'm tring to learn how to use Ionic framework,
I've made a controller to get some data from a database using play 2.0 as web server.
This is my factory code :
.factory('Projects', function($http) {
var projects = [];
return {
getProjects: function() {
$http.defaults.headers.post['Content-Type'] = 'application/json';
return $http({
method: 'POST',
url: 'http://localhost:8101/getProjects',
dataType: 'json',
headers: { 'Content-Type': undefined }
}).success(function(data, status) {
projects= data;
return projects
}).error(function(arg) {
alert("error ");
});
}
}
})
and my controller :
.controller('RootsCtrl', function($scope, Projects, $http) {
$scope.projects= Projects.getProjects();
})
and here is my view :
<ion-view view-title="Projects">
<ion-content>
<ion-list>
<ion-item class="item-remove-animate item-avatar item-icon-right" ng-repeat="project in projects" type="item-text-wrap" >
<h2>{{project.try}}</h2>
</ion-item>
</ion-list>
</ion-content>
</ion-view>
The web server only return some fake data by now.
I can't understand why, in my view, the value for project.try isn't show, but the row is present.
So if I have two values, in my html I can see two row, but without their "name".
Thanks
Factories are singletons and return an object that contains the members of the service.
.factory('Project', function($http, $log) {
return {
getProjects: getProjects
};
function getProject(){
var config = {
method: 'POST',
url: 'http://localhost:8101/getProjects',
headers: { 'Content-Type': undefined }
}
return $http(config).then(success).catch(failure);
}
function success(resp){
return resp.data;
}
function failure(error){
return error;
}
});
$http returns a promise.
//Controller
.controller('RootsController', function(Project){
var vm = this;
fetchProject();
function fetchProject(){
Project.getProject().then(success, failure);
}
function success(data){
vm.projects = data;
}
function failure(err){
// Error Handling
}
});
In your view:
<ion-item ng-repeat = "project in vm.projects">
{{project}}
</ion-item>
Also in your states:
controller: 'RootsController as vm' because Ionic has issues with controllerAs syntax.
Also you are not posting any data? And you can see just rows and not names because the project object exists but might not contain a key called try
Related
I wrote a controller for login page. Here is my controller:
var authApp = angular.module('loginApp', [])
authApp.controller('LoginCtrl', ['$scope', '$location', 'loginFactory', function($scope, $location, loginFactory){
$scope.authenticate = function() {
loginFactory.login($scope.username, $scope.password)
.then(function(response) {
console.log(response.$statusText);
}, function errorCallBack(response) {
console.log(response.$statusText);
});
}
}]);
My service:
authApp.factory("loginFactory", function ($http) {
return{
login: function(username, password) {
var data = "username="+username+"&password="+password+"&submit=Login";
return $http({
method: 'POST',
url: 'http://localhost:8080/login',
data: data,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
}
});
}
When I debug the code, authentication seems successful and it did get into then function. However nothing displays in console. And I got a warning(?) saying undefined for the line console.log(response.$statusText);. It is not an error since it is not red. Why doesn't it print out anything?
Use response.statusText not response.$statusText. The documentation for AngularJS $http requests lists statusText as one of the properties of the response object - https://docs.angularjs.org/api/ng/service/$http
I have tried to pass the customer class object to Asp.net MVC controller using angularJS $http service.
var app = angular.module("myApp", []);
app.controller("myCtrl", function ($scope,$http)
{
$scope.getRecord = function () {
$scope.objCustomer = { Id: 5, Name: 'sasi', Dept: 'IT' };
$http({ url: "Home/GetCustbyID",
method: "GET",
params: {objCustomer: $scope.objCustomer} })
.then(function (response)
{
//success code
};});
}});
Controller Action is defined like:
public JsonResult GetCustbyID(Customer objCustomer)
{
return Json(objCustomer, JsonRequestBehavior.AllowGet);
}
However in the above controller action customer object is always passed as null. Did i miss anything?
Please help me guys to resolve this.
You should use a POST request if you wish to send multiple parameters at once in a JSON object in your AJAX request and capture that as an Object on your server side.
$http.post(url, $scope.objCustomer)
.then(successCallback, errorCallback);
As you are actually sending data to server you are posting in $http.
var app = angular.module("myApp", []);
app.controller("myCtrl", function ($scope,$http)
{
$scope.getRecord = function () {
$scope.objCustomer = { Id: 5, Name: 'sasi', Dept: 'IT' };
$http({
url: "Home/GetCustbyID",
method: "POST",
data: $.param({ objCustomer : $scope.objCustomer })
})
.then(function(response) {
//success code
};});
}});
in other case if you like to send/pass data as json string you will have to use stringify like this
var data = $.param({
json: JSON.stringify({
name: $scope.name
})
});
$http.post("/path_of_controller", data).success(function(data, status) {
//do whatever you like
})
I am trying to do a http ququest in angular. Somehow it seems am missing out on something which i cannot figure out what it is?
On Page load i get this error:
Error: [$injector:undef] http://errors.angularjs.org/1.4.5/$injector/undef?p0=%24formServices
My Service:
app.factory('$formServices',['$http','$q',function ($http, $q) {
function postSubmit (fData) {
return $http({
url: 'forms/Form1.php',
method: "POST",
data: { items: JSON.stringify(fData) }
});
}
}
]
);
And the controller that calls the service:
$formServices.postSubmit($scope.Parameters).then(function (response) {
console.log(response);
$scope.Results = response;
});
What am i missing out on?
$injector:undef
Try adding a return to your factory. Also, if you wish to call the function with dot notation you need to place the function inside of an object.
app.factory('$formServices',['$http','$q',function ($http, $q) {
return {
postSubmit: function(fData) {
return $http({
url: 'forms/Form1.php',
method: "POST",
data: { items: JSON.stringify(fData) }
});
}
}
}
]
);
Factory must return object from factory, so that will be exposed via to factory consumer via injecting its dependency.
Code
app.factory('$formServices', ['$http', '$q', function($http, $q) {
function postSubmit(fData) {
return $http({
url: 'forms/Form1.php',
method: "POST",
data: {
items: JSON.stringify(fData)
}
});
}
// should object
return {
postSubmit: postSubmit //link post submit to function
}
}]);
The issue is that your factory does not return an object. To learn more about this I suggest reading https://docs.angularjs.org/guide/providers
Evilzebra's answer would work I believe, but if you ever wanted to have more functionality in your factory, a good way to structure factories is:
app.factory('$formServices',['$http','$q',function ($http, $q) {
var service = {};
service.postSubmit = function (fData) {
return $http({
url: 'forms/Form1.php',
method: "POST",
data: { items: JSON.stringify(fData) }
});
}
return service;
}]);
This would allow you to add more features, appending them to the service object.
I have been trying AngularJS for a experimental project and I came along with this problem.
In my html I want to display a list of items
Index.html
<h1>Some list</h1>
<div ng-controller="datlist">
<div ng-repeat="item in items">
<div>Item description: {{item.description}}</div>
<div>Item name: {{item.name}}</div>
</div>
</div>
At first I was using a simple controller to get the information and update the view just using this:
controllers.js (original)
function datlist($scope,$http){
$http({method: 'GET', url: 'http://localhost:61686/getdatlist?format=json', headers: {'Access-Control-Allow-Origin': 'localhost:*'}}).
success(function(data, status, headers, config) {
$scope.items=data.itemsToReturn;
console.log(data);
}).
error(function(data, status, headers, config) {
console.log("fail");
});
}
This was working pretty well and I could get the list of items. Whilst, by changing my structure to use a factory to make the same request and bind it to $scope.items it doesn't work. I tried a lot of variations of $watch but I couldn't get it to update $scope.items. I found something about $apply but I really can't understand how to use it.
controllers.js (new one)
var datModule = angular.module('datModule',[]);
datModule.controller('datlist', function ($scope, datfactory){
$scope.items = datfactory.getlist();
$scope.$watch($scope.items, $scope.items = datfactory.getlist());
});
datModule.factory('datfactory', function ($http){
var factory = {};
factory.getlist = function(){
$http({method: 'GET', url: 'http://localhost:61686/getdatlist?format=json', headers: {'Access-Control-Allow-Origin': 'localhost:*'}}).
success(function(data, status, headers, config) {
console.log(data.itemsToReturn); //I get the correct items, all seems ok here
return data.itemsToReturn;
}).
error(function(data, status, headers, config) {
console.log("fail");
});
}
return factory;
});
Any ideas about this will be great.
PS: I found a lot of posts talking about this issue but none of them helped me to get a full solution.
Thanks
Using a watch for that is kinda ugly.
try this:
datModule.factory('datfactory', function ($http, $q){
this.getlist = function(){
return $http.get('http://localhost:61686/getdatlist?format=json',{'Access-Control-Allow-Origin': 'localhost:*'})
.then(function(response) {
console.log(response); //I get the correct items, all seems ok here
return response.data.itemsToReturn;
});
}
return this;
});
datModule.controller('datlist', function ($scope, datfactory){
datfactory.getlist()
.then(function(arrItems){
$scope.items = arrItems;
});
});
This is how you use promises for async matter.
UPDATE (15.01.2015): Now even sleeker!
The issue is nothing to do with the scope digest cycle. You are trying to return from inside a callback directly, which is not asynchronously possible.
I recommend you either use a promise, or return the http promise directly.
var factory = {};
factory.getlist = function(){
return $http({method: 'GET', url: 'http://localhost:61686/getdatlist?format=json', headers: {'Access-Control-Allow-Origin': 'localhost:*'}});
}
return factory;
To return the promise directly, and handle the success/fail at factory.getlist().success()
Alternatively, use your own promise if you want to wrap additional logic around the request.
var datModule = angular.module('datModule',[]);
datModule.controller('datlist', function ($scope, datfactory){
$scope.items = [];
datfactory.getlist().then(function(data) { $scope.items = data });
});
datModule.factory('datfactory', function ($http, $q){
var factory = {};
factory.getlist = function(){
var defer = $q.defer();
$http({method: 'GET', url: 'http://localhost:61686/getdatlist?format=json', headers: {'Access-Control-Allow-Origin': 'localhost:*'}}).
success(function(data) {
// alter data if needed
defer.resolve(data.itemsToReturn);
}).
error(function(data, status, headers, config) {
defer.reject();
});
return defer.promise;
}
return factory;
});
try to initialize $scope.items = []; at controller, before call $http
I hope it helps you.
Well it looks perfect but you can use $apply like this.
datModule.controller('datlist', function ($scope, datfactory){
$scope.$apply(function() {
$scope.items = datfactory.getlist();
});
});
I think another elegant solution to this problem could be - if you are using one of the routing libraries, in my case it is the UI-Router, but could be also ngRoute, is making your controller dependent on the response of the promise, eg. adding a resolve property to the adequate state/route which doesn't let the controller load until the promise is solved and the data is ready, so in your config:
.state('datpage', {
url: '/datpage',
controller: 'DatpageController',
resolve:{
datData: function (datfactory) {
return datDataService.getData("datDataParam");
}]
},
templateUrl: 'views/datpage.html'
})
And inject the datData dependency in your controller, where you can apply it directly to the $scope:
.controller('DatpageController', function ($scope,datData) {
$scope.datPageData = datData; ...
When my ng page loads containing the ng-repeat markup below, it renders the IMG tag before the iterator is populated, but because no src value is present, that generates a 404 for the partial src.
<div ng-repeat="item in preview_data.items">
<h4>{{item.title}}</h4>
<img src="{{item.thumb}}" />
</div>
Then my controller kicks in and populates it with the right list of videos.
How do I stop the HTML from getting rendered until the controller is ready with the data?
The page is called by this route:
app.config(function ($routeProvider, $locationProvider ) {
$locationProvider.html5Mode(true);
console.log('config');
$routeProvider.when("/", {
templateUrl: "/templates/createFeed.html",
controller: "CreateFeedController"
});
});
which calls a factory to get a list of videos to preview from the backend api:
app.controller("CreateFeedController", function ($scope, $route, $sce, Preview) {
var keywords = decodeURIComponent($route.current.params.keywords);
$scope.preview_data = {
keywords: keywords
}
//pass parameters to web preview API
Preview.get(keywords, function (data) {
$scope.preview_data.items = data;
});
});
app.factory('Preview', function ($http) {
return{
get: function (keywords, next) {
$http({method: 'GET', url: '/api/preview/', json:true,
params: {keywords: keywords}}
).success(function (data) {
// prepare data here
//console.log(data);
next(data);
});
}
};
});
You must use the ng-src directive instead of the plain src attribute in your img tag.
From the Angular API for ng-src:
The browser will fetch from the URL with the literal text {{hash}} until Angular replaces the expression inside {{hash}}. The ngSrc directive solves this problem.
Check the ng-cloak directive.It's intended exactly for this.
http://docs.angularjs.org/api/ng.directive:ngCloak
As you know $http returns promise. Therefore your factory is async.
So factory should be like:
app.factory('Preview', function ($http, $q) {
return{
get: function (keywords, next) {
var deferred = $q.defer();
$http({method: 'GET', url: '/api/preview/', json:true,
params: {keywords: keywords}}
).success(function (data) {
deferred.resolve(data);
}).error(function() {
deferred.reject("Error ...");
});
//Returning the promise object
return deferred.promise;
}
};
});
And controller:
Preview.get(keywords) // returns promise
.then(function (result) {
$scope.preview_data.items = result;
}, function (result) {
alert("Error: No data returned");
});