angular 1.5 component wait data - angularjs

i am trying to use au component in order to display my data.
In my template i have :
{{myDatas}}
<my-cmp data="myDatas"></my-cmp>
i displayed {{myDatas}} to be sure there was data
here is my code for my component :
(function() {
'use strict';
angular
.module('myApp.test')
.controller('TestController', TestController)
.component('myCmp', {
templateUrl: 'myTemplate.html',
bindings: {
data: '='
},
controller: myController
});
function TestController($scope, $stateParams, ResidencesFactory) {
$scope.myDatas = TestFactory.read({id: $id});
}
function myController($scope) {
console.log($scope.$ctrl.data.nbElements);
}
})();
This code doesn't works.
But if i replace $scope.myDatas with the expected JSON, it works.
here is the code of TestFactory :
(function () {
'use strict';
angular
.module('core.test')
.factory('TestFactory', TestFactory);
function TestFactory($resource) {
return $resource(
'/api/test/:id',
{
id: '#id'
},
{
query: {
method: 'GET',
isArray: true
},
read: {
method: 'GET'
}
}
);
}
})();
So i think i have to wait the data from the $resource of my TestFactory but how can i do this ?
Thanks
EDIT
here is what i did. i replaced
$scope.myDatas = TestFactory.read({id: $id});
with
TestFactory.read({id: $id}).$promise.then(function(response){
$scope.myDatas = response;
});
And in my component controller, i had the $onInit like this :
this.$onInit = function () {
console.log($scope.$ctrl.data);
$scope.percent = parseFloat(($scope.$ctrl.data.nbElements/ $scope.$ctrl.data.nbAllElements * 100).toFixed(2))
}
But in the chrome console, it tells me that $scope.$ctrl.data is undefined, and the error "TypeError: Cannot read property 'nbElements' of undefined
if i do
console.log($scope.$ctrl);
i have this in chrome console :
>myController
>$onInit: function()
>data: m
>__proto__:Object
Chrome tell me myCotroller was evaluated so i think myCotroller is not waiting the data before building my properties. What am i doing wrong ?

problem solved adding an ng-if condition in my template
<my-cmp ng-if="myDatas" data="myDatas"></my-cmp>
thanks for your help

Related

Unable to inject my service in Angular resolve inside router configuration

(My plunkr code resides at http://plnkr.co/edit/6KU3GblQtMdRAx3v3USV?p=preview)
I'm trying to create a Search bar (in navigation) which should ultimately hit the backend REST API. The input search button when clicked on input 'alpha' would trigger a route to products/search/0?searchtext=alpha
Clicking on the button triggers a route change, which should do resolve as follows:
.when("/products/search/:page", {
templateUrl: "products.html",
controller: "ProductsSearchController",
resolve: {
// Define all the dependencies here
ProdSearchServ : "ProdSearchService",
// Now define the resolve function
resultData : function(ProdSearchServ) {
return ProdSearchServ.searchProducts();
}
}
})
However, I'm getting the following error
angular.js:9784 Error: [$injector:unpr] Unknown provider: ProdSearchServProvider <- ProdSearchServ
I believe I'm doing most of the things as per conventions, may be I'm missing something here?
I'm copying script.js code below (also in plnkr link above). It has all the route configuration and the controllers defined.
(function(){
// jargoViewer Create a new Angular Module
// This would go into the html tag for index.html
var app = angular.module("jargoViewer", ["ngRoute"]);
app.config(function($routeProvider){
$routeProvider
.when("/main", {
templateUrl: "main.html",
controller: "NavController"
})
.when("/products/search/:page", {
templateUrl: "products.html",
controller: "ProductsSearchController",
resolve: {
// Define all the dependencies here
ProdSearchServ : "ProdSearchService",
// Now define the resolve function
resultData : function(ProdSearchServ) {
return ProdSearchServ.searchProducts();
}
}
})
.otherwise({redirectTo:"/main"});
});
}());
// Nav Controller
(function() {
var app = angular.module("jargoViewer");
var NavController = function($scope, $location) {
// Function to invoke the Prod search based on input
$scope.search = function() {
console.log("searchText : " + $scope.searchtext);
$location.path("products/search/0").search({searchtext: $scope.searchtext});
};
};
app.controller("NavController", NavController);
}());
// Define the Prod Search Service here
(function() {
// Get reference to the app
var app = angular.module("jargoViewer");
// Create the factory
app.factory('ProdSearchService', function($routeParams, $http, $q) {
var searchProducts = function() {
pageNum = 0;
searchParam = '';
if (('page' in $routeParams) && (typeof $routeParams.page === 'number')) {
pageNum = $routeParams.page;
}
// Check if the router Param contains the field searchtext, if so, check if its a string
if (('searchtext' in $routeParams) && (typeof $routeParams.searchtext === 'string')) {
searchParam = $scope.routeParam.searchtext;
}
// Now make the http API hit to fetch the products
var request = $http({
method: "get",
url: "http://abcd.com/products/search/" + pageNum,
params: {
search: searchParam
},
});
return(request.then(handleSuccess, handleError));
};
function handleError(response) {
// The API response from the server should be returned in a
// nomralized format. However, if the request was not handled by the
// server (or what not handles properly - ex. server error), then we
// may have to normalize it on our end, as best we can.
if (
! angular.isObject(response.data) ||
! response.data.message
) {
return($q.reject( "An unknown error occurred."));
}
// Otherwise, use expected error message.
return($q.reject(response.data.message));
}
// I transform the successful response, unwrapping the application data
// from the API response payload.
function handleSuccess(response) {
if(response.data.error == true) {
return($q.reject(response.data.message));
}
return(response.data.data);
}
return {
searchProducts : searchProducts
};
});
}());
// Define the Products Search Controller below
(function() {
var app = angular.module("jargoViewer");
//var ProductController = function($scope) {
var ProductsSearchController = function($scope, $routeParams, ProdSearchService) {
// Nothing to do really here
};
app.controller("ProductsSearchController", ProductsSearchController);
}());
This caused by your bizarre naming conventions. Sometimes ProdSearchServ and sometimes ProdSearchService.
If you just pick one and use it consistantly then you won't run into these types of errors.
Fixed Plunker
In particular you create the service with the name ProdSearchService and then attempt to use it with a different name:
app.factory('ProdSearchService',
//vs
resultData : function(ProdSearchServ) {
I imagine you we under the impression that this code would fix it for you. However, this only applies to dependencies passed into the controller, not functions in general. For services which already exist, you do not need to define them specially like this; instead simply use the correct name in the controller.
// Define all the dependencies here
ProdSearchServ : "ProdSearchService",
I think you don't need to define the dependency when you say
// Define all the dependencies here
ProdSearchServ : "ProdSearchService",
Just do this:
.when("/products/search/:page", {
templateUrl: "products.html",
controller: "ProductsSearchController",
resolve: {
resultData : function(ProdSearchService) { //as you defined it before
return ProdSearchService.searchProducts();
}
}
})
There is a similar question here

Angular factory and controller

I am trying to learn about using factory with controller. I have seen one example with:
angular.module('flapperNews')
.factory('posts', ['$http', function($http) {
var o = {
posts: []
}
o.getPosts = function() {
return $http.get('api/posts').success(function(data) {
return data
})
};
o.create = function(post) {
return $http.post('api/posts', post).success(function(data) {
o.posts.push(data);
})
};
return o
}])
When I console.log(o.getPosts()), it returned the following:
Promise {$$state: Object}
$$state
:
Object
pending
:
undefined
processScheduled
:
false
status
:
1
value
:
Object
config
:
Object
data
:
Array[6]
0
:
Object
_id
:
"576d4904f2aa867dadb7b286"
link
:
"aaa"
title
:
"nice weather in Australia"
upvotes
:
0
__proto__
:
Object
__defineGetter__
:
__defineGetter__()
__defineSetter__
:
__defineSetter__()
__lookupGetter__
:
__lookupGetter__()
__lookupSetter__
:
__lookupSetter__()
constructor
:
Object()
hasOwnProperty
:
hasOwnProperty()
isPrototypeOf
:
The data I wanted is under Array[6] which is under $$state, does anyone have any idea what this is and how does one normally extract that data?
The data is supposed to be passed to my controller like so:
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'views/posts.html',
controller: 'PostCtrl',
controllerAs: 'posts',
resolve: {
postPromise: ['posts', function(posts) {
console.log(posts.getPosts())
return posts.getPosts();
}]
}
});
Note:This is taken from an online tutorial. Would really appreciate it if someone can shed some light on this as I am new to factory etc. The current code doesn't return anything to my view, can you tell me where I have gone wrong?
Edited/Added: This is the implementation of controller. When I console.log(posts.posts) it returns an empty array []. Any ideas?
angular.module('flapperNews')
.controller('PostCtrl', [
'$scope','posts',
function($scope,posts){
$scope.posts=posts.posts;
$scope.incrementUpvotes=function(post){
post.upvotes+=1
}
$scope.addPost = function(){
if(!$scope.title || $scope.title === '') { return; }
posts.create({
title: $scope.title,
link: $scope.link,
});
$scope.title = '';
$scope.link = '';
};
}]);
How are you calling the factory's method in your controller? You are making an $http request which returns a promise.
You can learn about promises here:http://andyshora.com/promises-angularjs-explained-as-cartoon.html.
In short you can see promises as functions that execute right away but return data in the future (not right away). You will have to wait until the promise "resolves" to get the data. That is why is good to wrap any code that needs data from a promise, within the promise function itself.
In your controller you should call the factory method(getPosts()) like this:
posts.getPosts().then(function(response){
$scope.news = response.data; <---here is where you get your data for your news. You cant not declare **$scope.data** outside this promise function because you will miss the data.
});
Don't forget to inject your posts service/factory in your controller like this:
controller(['posts',function(posts){ ... });
You can also get the data in your route like this:
$stateProvider
.state('home',{
url:'/home',
templateUrl:'views/posts.html',
controller:'PostCtrl',
controllerAs:'posts',
resolve:{
postPromise: ['posts', function(posts){
return posts.getPosts().then(function(response){
return response.data
});
}]
}
})
Then in your controller you can inject the postPromise like this:
controller(['postPromise',function(postPromise){ ... });
Now you can assign the data to a variable in your controller like this:
$scope.news = postPromise;
Hope I answered your question. If I misunderstood please give more details or provide a codepen.

passing complex type as param

Angular js / angular ui router 0.2.15
I am trying to pass complex js array into the controller using $state.go
Following is my code can you help. looks like following code throwing error
Error: [$injector:unpr] http://errors.angularjs.org/1.2.28/$injector/unpr?p0=servicesProvider%20%3C-%20services
.js file
var services = {complex type};
$state.go("linearOfferProcess", {'services': services});
in my route.js
state('linearOfferProcess', {
url: '/linearOfferProcessor',
templateUrl: '/partials/linear_process.html',
controller: 'linearProcessController',
services:
function($stateParams) {
return $stateParams.services;
}
}
controller
angular.module('app').controller('linearOfferProcessController',function($scope) {
$scope.services = services;
});
Unfortunately I don't know any possible of accomplishing this, but you could try doing it using a Factory. I made a small mockup for you, in the container I'm storing the services and creating a unique ID for every complex object. So you can retrieve it whenever you want.
angular.module('app').factory('ServicesContainer', function() {
var counter = 1;
return {
container: {},
add: function(services) {
container[counter] = services;
return counter;
}
};
});
angular.module('app').controller('SomeController', function(ServicesContainer, $state) {
var id = ServicesContainer.add({ complex object });
$state.go('services', {
id: id
});
});
angular.module('app').config(function($stateProvider) {
$stateProvider.state('services', {
url: '/{id}',
onEnter: function(ServicesContainer, $stateParams, $log) {
$log.info('Services', ServicesContainer[$stateParams.id]);
}
});
});

AngularJS promises behavior

I have some code using angularJS.
In my application initialization logic, I keep geting an error, but I can't figure out why.
I think this may be a problem with the promise.
Here is my controller:
// TeacherCtrl.js
(function () {
"use strict";
angular
.module("app.controllers")
.controller("TeacherController", TeacherController)
.config(["$routeProvider", config]);
TeacherController.$inject = ["DataService"];
function TeacherController(DataService) {
var vm = this;
vm.data = {};
begin(7, 163000001);
function begin(appId, schoolId) {
DataService.GetData(appId, schoolId).then(function (data) {
console.log(data);
});
}
}
function config($routeProvider) {
$routeProvider
.when("/teacher", {
"templateUrl": "components/teacher/teacher.html"
, "controller": "TeacherController"
, "controllerAs": "vm"
});
}
})();
And here is my service:
// app.services.js
(function () {
"use strict";
angular
.module("app.services")
.factory("DataService", ApplicationData);
DataService.$inject = ["KeysResource"];
function DataService(KeysResource) {
return {
"GetData": GetData
};
function GetData(appId, schoolId) {
return KeysResource.load({
"appId": appId,
"schoolId": schoolId
});
}
}
})();
and this is the error I am getting:
TypeError: undefined is not a function
at iniciar (http://my.url/TeacherCtrl.js:18:72)
at new TeacherController (http://my.url/TeacherCtrl.js:15:9)
at .. // angular js code here
What it's looks like is that the ".then" function for the promise is not immediately available. Shouldn't it be???
EDIT
Here is the KeysResource I've mentioned
"use strict";
(function () {
var restClient = angular.module("restClient", ["ngResource"]);
var serviceURL;
restClient
.factory("KeysResource", ["$resource", function ($resource)
{
serviceURL = "http://my.url/service/";
return $resource(serviceURL, null, {
"load": {
"method": "get",
"url": serviceURL + "load"
}
});
}]);
})();
I've found this question with a similar problem.
The solution is related to $resource, which does not return a promise directly. If I want to use the promise of $resource, I will need to use $promise too, like that:
//TeacherCtrl.js
function begin(appId, schoolId) {
DataService.GetData(appId, schoolId).$promise.then(function (data) {
console.log(data);
});
}

Firebase + angularfire getting current user before controller loads

I'm following the official examples to fetch the user before the angular controller is fired but the controller is never fired when using this method. If I remove the resolve: state_resolver line the controller fires which means my resolver has something wrong. Any ideas what am I doing wrong here?
.config(function($stateProvider) {
var state_resolver;
state_resolver = {
"current_user": [
"simpleLogin", function(simpleLogin) {
return simpleLogin.$getCurrentUser();
}
]
};
return $stateProvider.state("dash", {
url: "/dash",
templateUrl: "templates/dash.html",
controller: "DashCtrl",
resolve: state_resolver
});
});
If the following example using $timeout works, then you probably have an issue with your simpleLogin service which does not respond.
.config(function($stateProvider) {
var state_resolver;
state_resolver = {
"current_user": function($timeout) {
return $timeout(function () {console.log('OK');}, 5000);
}
};

Resources