Angularjs getting data from controller scope to directive scope - angularjs

I am trying to get data from resource then add it to isolate scope of directive but when i want to print it to screen i get error as undefined current_page here is the script
/**
* Created by yigit on 10.01.2014.
*/
var app = angular.module('kategori', [
'ngResource',
'apiBaseRoute'
]);
app.factory('Data', ['$resource', 'apiBaseRoute', function($resource, config){
return $resource(config.apiBasePath + 'kategori/?page=:page',{page:1},{
query:{
isArray: false,
method: 'GET'
}
});
}]);
app.controller('KategoriListCtrl',['$scope', 'Data', function($scope, Data){
$scope.allData = {data:null};
Data.query({}, function(data){
$scope.kategoriList = {data:data.cat.data};
$scope.allData.data = data.cat;
});
}]);
app.directive('paginate', function(){
return{
scope:{paginatorData: '=paginate'},
link: function(scope){
alert(scope.paginatorData.current_page);
}
}
});
<!DOCTYPE html>
<html ng-app="kategori">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="css/bootstrap.min.css">
</head>
<body>
<div class="col-md-6 col-md-offset-3" ng-controller="KategoriListCtrl">
{{allData.current_page}}
<div paginate="allData"></div>
</div>
<script src="js/lib/angular.min.js"></script>
<script src="js/lib/angular-resource.js"></script>
<script src="js/kategori.js"></script>
<script src="js/apiroute.js"></script>
</body>
</html>
I read this article nested scope
But could not solve my problem.
So, the code alerts undefined. How can i solve this?

Can you show your HTML? You'll need to pass the property like this:
<div data-paginate="paginate"></div>

Related

Angular Controller is not triggering

My controller is not triggering. It should be stupid but I can't see why.
Here find my code structure.
Please help me find that basic error.
template :
<!DOCTYPE html>
<html ng-app="attachmentsApp" ng-cloak="">
<head>
<meta charset="utf-8"/>
<script th:inline="javascript">
/*<![CDATA[*/
var source = [[${source}]];
var appContext = /*[[#{/}]]*/ '';
/*]]>*/
</script>
</head>
<body>
<div th:replace="include"></div>
<script th:src="#{/app/modules/attachments/scripts/attachmentsapp.js}"></script>
<script th:src="#{/app/modules/attachments/scripts/controllers/AttachmentsHomeCtrl.js}"></script>
<script th:src="#{/app/modules/attachments/scripts/services/AttachmentsHomeService.js}"></script>
</body>
</html>
App :
angular
.module('attachmentsApp', ['ngRoute'
]).run(['$rootScope', function($rootScope){
$rootScope.appContext = window.appContext;
$rootScope.language = window.language;
$rootScope.source = window.source;
}])
.config(function($routeProvider) {
$routeProvider.when('/', { templateUrl: window.appContext + 'app/modules/attachments/views/home.html', controller: "AttachmentsHomeCtrl" })
});
Controller:
angular.module('attachmentsApp').controller('AttachmentsHomeCtrl', ['$scope','$rootScope','AttachmentsHomeService','$window',
function ($scope,$rootScope,AttachmentsHomeService,$window) {
console.log($rootScope.source);
debugger;
}]);
Service :
'use strict';
angular.module('attachmentsApp').service('AttachmentsService', [ '$http', '$rootScope', function($http, $rootScope){
this.getForm = function(type) {
debugger;
}
return this;
}]);
Many thanks
Suggesting some change in your HTML:
1) Define and load files before their use: ng-app was being used before attachmentsapp.js file is loaded in DOM
2) Order of usage: service file was loaded after its usage in controller
It should be look like:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<script th:inline="javascript">
/*<![CDATA[*/
var source = [[${source}]];
var appContext = /*[[#{/}]]*/ '';
/*]]>*/
</script>
<script th:src="#{/app/modules/attachments/scripts/attachmentsapp.js}"></script>
<script th:src="#{/app/modules/attachments/scripts/services/AttachmentsHomeService.js}"></script>
<script th:src="#{/app/modules/attachments/scripts/controllers/AttachmentsHomeCtrl.js}"></script>
</head>
<body ng-app="attachmentsApp" ng-cloak="">
<div th:replace="include"></div>
</body>
</html>
Not 100% sure, but it should be working. Do a try !!
Moreover, keep an eye on console.
It was the Service name.
AttachmentsHomeService as registering it in Controller
AttachmentsService in service definition
Many thanks for your help

data to read my json file in IONIC

This world is sad to cry , am blocked for two hours with a problem that i couldnt define ,i can't retrieve data from my json file ,everything in my code seems correct.
This is my factory:
'use strict';
angular.module('starter.services')
.factory('userService',function ($http) {
return{
getUsers:function(){
return $http.get("http://localhost:26309/api/User/getAll/").then(function (response) {
return response.data;
});
}
}
});
and this controller :
'use strict';
angular.module('starter.controllers', ['starter.services'])
.controller('UsersCtrl', function($scope,userService) {
$scope.Users = [];
userService.getUsers().then(function (data) { $scope.Users= data.data; }); });
});
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<title></title>
<link href="lib/ionic/css/ionic.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
<!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above
<link href="css/ionic.app.css" rel="stylesheet">
-->
<!-- ionic/angularjs js -->
<script src="lib/ionic/js/ionic.bundle.js"></script>
<script src="lib/ionic/js/angular/angular-resource.min.js"></script>
<!-- cordova script (this will be a 404 during development) -->
<script src="cordova.js"></script>
<!-- your app's js -->
<script src="js/app.js"></script>
<script src="js/UserControllerIonic.js"></script>
<script src="js/UsersServiceIonic.js"></script>
</head>
<body ng-app="starter" ng-controller="UsersCtrl">
<ion-view>
<div class = "list" >
<a class = "item" ng-repeat = "user in Users">
<h2>{{user.nom}}</h2>
</a>
</div>
</ion-view>
</body>
</html>
Thank you in advance
SOLUTION
i solved the problem by :
1- adding in the config.xml the permission <allow-navigation href="http://*/*"/>
2-installing cordova-plugin-whitelist ionic plugin add cordova-plugin-whitelist
3-add control-allow-origin extention to chrome :https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi/related?hl=en-US
and finally : specifying the type of data returned by the back-end controller by adding this code to my Global.asax in Application_start method :config.Formatters.JsonFormatter.SerializerSettings.Formatting =
Newtonsoft.Json.Formatting.Indented;
config.Formatters.Remove(config.Formatters.XmlFormatter);
hope this helps someone
You don't want to resolve your $http call inside factory.
JS:
angular.module('app',[])
.controller('MainCtrl', function($scope, MyService){
var url = "http://jsonplaceholder.typicode.com/users";
MyService.getData(url).then(function(res){
console.log(res.data);
$scope.data = res.data;
});
})
.service('MyService', function($http){
return {
getData: function(url){
return $http.get(url);
}
}
})
HTML:
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-controller="MainCtrl">
<ul>
<li ng-repeat="item in data">{{item.name}}</li>
</ul>
</body>
</html>
The issue is that you are resolving the promise in service with the value response.data, and again expecting the resolved value to have data property. Change your service code as below:
'use strict';
angular
.module('starter.services')
.factory('userService',function ($http) {
return {
getUsers: function(){
return $http.get("http://localhost:26309/api/User/getAll/").then(function (response) {
return response;
});
}
}
});
Or simply return the promise as below:
'use strict';
angular
.module('starter.services')
.factory('userService',function ($http) {
return {
getUsers: function(){
return $http.get("http://localhost:26309/api/User/getAll/");
}
}
});

Google Signin button in AngularJS sometimes does not show up

I followed this link https://developers.google.com/identity/sign-in/web/sign-in to get Google Signin on Angular-based website.
I have seen some weird behavior. The signin button sometimes show but not always. When I refresh a page, only 1 in 5 refreshes, the button appears.
I tried in Chrome and Safari and both has same behavior.
Code:
index.html
<script src="https://apis.google.com/js/platform.js" async defer></script>
<meta name="google-signin-client_id" content="my_client_id">
login.html
<div class="g-signin2" data-onsuccess="onSignIn"></div>
login.js
angular.module('app').controller('LoginCtrl', function($scope) {
window.onSignIn = function(googleUser) {
// Get some info
}
});
My guess is that the platform.js script waits for the DOM-ready event and then looks for your div with the "g-signin2"-class. Though, in Angularjs things work a little different. The reason that it works sometimes, is because sometimes your div has been rendered by Angular and sometimes is hasn't been rendered before the Dom-ready event.
There's documentation on how to get the same result with your own javascript.
I made an example that follows your routing.
<!doctype html>
<html lang="en" ng-app="app">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div ng-view></div>
<script src="https://apis.google.com/js/platform.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular.min.js"></script>
<script src="https://code.angularjs.org/1.4.6/angular-route.min.js"></script>
<script>
angular.module('app',['ngRoute'])
.config(['$routeProvider',function($routeProvider){
$routeProvider
.when('/log-in', {
template: '<button ng-click="logInCtrl.onLogInButtonClick()">Log In</button>',
controller: 'LogInController',
controllerAs: 'logInCtrl'
}).otherwise({
redirectTo:'/log-in'
});
}])
.controller('LogInController',function(){
var self = this; //to be able to reference to it in a callback, you could use $scope instead
gapi.load('auth2', function() {//load in the auth2 api's, without it gapi.auth2 will be undefined
gapi.auth2.init(
{
client_id: 'CLIENT_ID.apps.googleusercontent.com'
}
);
var GoogleAuth = gapi.auth2.getAuthInstance();//get's a GoogleAuth instance with your client-id, needs to be called after gapi.auth2.init
self.onLogInButtonClick=function(){//add a function to the controller so ng-click can bind to it
GoogleAuth.signIn().then(function(response){//request to sign in
console.log(response);
});
};
});
});
</script>
</body>
</html>
Or as a directive:
<!doctype html>
<html lang="en" ng-app="app" ng-controller="MainController">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<google-sign-in-button on-sign-in="onSignIn(response)" g-client-id="CLIENTID.apps.googleusercontent.com"></google-sign-in-button>
<script src="https://apis.google.com/js/platform.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular.min.js"></script>
<script>
angular.module('app',[])
.controller('MainController',['$scope', function ($scope) {
$scope.onSignIn=function(response){
console.log(response);
}
}])
.directive('googleSignInButton',function(){
return {
scope:{
gClientId:'#',
callback: '&onSignIn'
},
template: '<button ng-click="onSignInButtonClick()">Sign in</button>',
controller: ['$scope','$attrs',function($scope, $attrs){
gapi.load('auth2', function() {//load in the auth2 api's, without it gapi.auth2 will be undefined
gapi.auth2.init(
{
client_id: $attrs.gClientId
}
);
var GoogleAuth = gapi.auth2.getAuthInstance();//get's a GoogleAuth instance with your client-id, needs to be called after gapi.auth2.init
$scope.onSignInButtonClick=function(){//add a function to the controller so ng-click can bind to it
GoogleAuth.signIn().then(function(response){//request to sign in
$scope.callback({response:response});
});
};
});
}]
};
});
</script>
</body>
</html>
After writing the previous examples I found a better and easier way to implement it. With this code you inherit the same button as you normally would.
<!doctype html>
<html lang="en" ng-app="app" ng-controller="MainController">
<head>
<meta charset="UTF-8">
<title>Document</title>
<meta name="google-signin-client_id" content="CLIENTID.apps.googleusercontent.com">
</head>
<body>
<google-sign-in-button button-id="uniqueid" options="options"></google-sign-in-button>
<script src="https://apis.google.com/js/platform.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular.min.js"></script>
<script>
angular.module('app', [])
.controller('MainController', ['$scope',
function($scope) {
//for more options visit https://developers.google.com/identity/sign-in/web/reference#gapisignin2renderwzxhzdk114idwzxhzdk115_wzxhzdk116optionswzxhzdk117
$scope.options = {
'onsuccess': function(response) {
console.log(response);
}
}
}
])
.directive('googleSignInButton', function() {
return {
scope: {
buttonId: '#',
options: '&'
},
template: '<div></div>',
link: function(scope, element, attrs) {
var div = element.find('div')[0];
div.id = attrs.buttonId;
gapi.signin2.render(div.id, scope.options()); //render a google button, first argument is an id, second options
}
};
});
</script>
</body>
</html>
I found another way to solve the problem a liitle bit simply.
The explanation from #sniel is perfect but I will let you know more simple solution.
you can use below sample code very simiraliry with using $watch
https://developers.google.com/identity/sign-in/web/build-button
<!-- html part -->
<div id="signInButton"></div>
//gapi is Asynchronously loaded so you need to watch
$scope.$watch('gapi', function(newValue,oldVale){
if(newValue !== oldVale){
if(gapi){
gapi.signin2.render('signInButton',
{
'onsuccess': $scope.onSuccess,
'onfailure': $scope.onFailure,
'scope':'https://www.googleapis.com/auth/plus.login'
}
);
}
}
});

How to update controller variable with 'ng-model' AngularJS?

I am trying to get user input through a text box using ng-model, and append to a base URL for a http.get call as follow;
index.html:
<html ng-app='vidRoute'>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Search Video</title>
<link rel="stylesheet" href="app/css/custom/main.css">
<link rel="stylesheet" href="app/css/custom/responsive.css">
</head>
<body>
<div id='mainwrapper'>
<div id='header' ng-controller="searchController">
<input type="text" id="searchTxt" ng-model="append">
Search Video
</div>
<div id="poster">
<div ng-view></div>
</div>
</div>
<script type="text/javascript" src="app/javascript/vendor/jquery-2.1.1.js"></script>
<script type="text/javascript" src="app/javascript/vendor/angular.js"></script>
<script type="text/javascript" src="app/javascript/vendor/angular-route.js"></script>
<script type="text/javascript" src="app/javascript/vendor/angular-resource.js"></script>
<script type="text/javascript" src="app/javascript/vendor/angular-mocks.js"></script>
<script type="text/javascript" src="app/javascript/custom/searchcontroller.js"></script>
<script type="text/javascript" src="app/javascript/custom/vidRoute.js"></script>
</body>
</html>
searchcontroller.js
'use strict';
var vidcontrol = angular.module("vidcontrol", []);
vidcontrol.controller("vidcontroller", ['$scope', '$http', function($scope, $http) {
$http.get('http://api.themoviedb.org/3/tv/airing_today?api_key=d5e87524383e2872a9555990b268dc5b').success(function(response) {
$scope.results = response.results;
});
}]);
vidcontrol.controller('searchController', ['$scope', '$http',
function ($scope, $http) {
var url = "http://api.themoviedb.org/3/search/movie?api_key=d5e87524383e2872a9555990b268dc5b&query=";
// var searchTxt = $('#searchTxt').val();// this works fine when used
var searchUrl = url + append; //$scope.append also logs 'undefined' on the console
$http.get(searchUrl).success(function (response) {
$scope.searchResults = response.results;
});
}]);
but I'm not getting any response. when I log searchUrl on console, I could see that append was not updated according to value from text box. I'm quite new to Angular and I can't figure out what I'm doing wrong. What should I do to fix this?
Now, I see the issue. When controller loaded, it executes controller code. That mean REST query runs before view is built. That is reason you see undefined problem. Solution is to define a method in controller which will be invoked when you click "Search Video".
Update view
Search Video //Look at ng-click
Update Controller:
vidcontrol.controller('searchController', ['$scope', '$http',function($scope, $http) {
var url = "http://api.themoviedb.org/3/search/movie?api_key=d5e87524383e2872a9555990b268dc5b&query=";
$scope.search = function(){ // Look at here, Defined a method to invoke on "Search Video" link click
var searchUrl = url + $scope.append;
$http.get(searchUrl).success(function(response) {
$scope.searchResults = response.results;
});
};
} ]);

sharing a var between views/controllers

I know this question has been asked 100s of times but i have yet to succeed in implementing this after reading countless of threads... shame on me.
I know this is a lot of code (sorry). But I just can't find what I'm doing wrong,
So to the problem I want to add something to the list in pat1 then click over to pat2 and see the same list.
Routing;
var routeApp = angular.module('routeApp', ['ngRoute', 'rootMod']);
routeApp.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/pat1', {
templateUrl: 'partials/pat1.html',
controller: 'pageOneCont'
}).
when('/pat2', {
templateUrl: 'partials/pat2.html',
controller: 'pageTwoCont'
}).
otherwise({
redirectTo: '/pat1'
});
}]);
Controllers & Service:
var rootMod = angular.module('rootMod', []);
rootMod.controller('pageOneCont', [ 'serv', '$scope', function (serv, $scope) {
'use strict';
// Your controller implementation goes here ...
$scope.handleClick = function ($scope, serv){
var updateFoo = function(){
$scope.foo = serv.foo;
};
aService.registerObserverCallback(updateFoo);
//service now in control of updating foo
};
}]);
rootMod.controller('pageTwoCont', [ 'serv', '$scope', function (serv, $scope) {
'use strict';
// Your controller implementation goes here ...
$scope.handleClick = function ($scope, serv){
var updateFoo = function(){
$scope.foo = serv.foo;
};
aService.registerObserverCallback(updateFoo);
//service now in control of updating foo
};
}]);
/* Service */
rootMod.factory('serv', [ function () {
var observerCallbacks = [];
//register an observer
this.registerObserverCallback = function(callback){
observerCallbacks.push(callback);
};
//call this when you know 'foo' has been changed
var notifyObservers = function(){
angular.forEach(observerCallbacks, function(callback){
callback();
});
};
}]);
INDEX.html
<!doctype html>
<html lang="en" ng-app="routeApp">
<head>
<script src="lib/angular/angular.js"></script>
<script src="lib/angular/angular-route.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
</head>
<body>
<li> ONE </li>
<li> TWO </li>
</body>
<!-- SinglePage -->
<div ng-view></div>
</html>
PAT1.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Angular Test</title>
<link rel="stylesheet" href="css/app.css">
<link rel="stylesheet" href="css/bootstrap.css">
<script src="lib/angular/angular.js"></script>
<script src="js/controllers.js"></script>
</head>
<div ><!--ng-app="myModule" ng-controller="ContactController">-->
<h1> ONE </h1>
<button ng-click="handleClick"> BROADCAST </button>
<div ng-repeat="item in foo">{{ item }}</div>
</div>
</html>
PAT2.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Angular Test</title>
<link rel="stylesheet" href="css/app.css">
<link rel="stylesheet" href="css/bootstrap.css">
<script src="lib/angular/angular.js"></script>
<script src="js/controllers.js"></script>
</head>
<div> <!--ng-app="myModule" ng-controller="ContactController">-->
<h1> TWO </h1>
<div ng-repeat="item in foo">{{ item }}</div>
</div>
</html>
JS
Your service is injected as serv in your controllers but you call aService. Use serv instead.
You should use rootMod.service() instead of rootMod.factory() since you are using this and not returning anything in your service function (see this for the difference between factories and services).
There is no serv.foo property. You have to add this.foo = /** something **/; to your service function.
So this should work:
var rootMod = angular.module('rootMod', []);
rootMod.controller('pageOneCont', [ 'serv', '$scope', function (serv, $scope) {
'use strict';
// Your controller implementation goes here ...
$scope.handleClick = function ($scope, serv){
var updateFoo = function(){
$scope.foo = serv.foo;
};
serv.registerObserverCallback(updateFoo);
// service now in control of updating foo
};
}]);
rootMod.controller('pageTwoCont', [ 'serv', '$scope', function (serv, $scope) {
'use strict';
// Your controller implementation goes here ...
$scope.handleClick = function ($scope, serv){
var updateFoo = function(){
$scope.foo = serv.foo;
};
serv.registerObserverCallback(updateFoo);
// service now in control of updating foo
};
}]);
/* Service */
rootMod.service('serv', [ function () {
var observerCallbacks = [];
// call this when you know 'foo' has been changed
var notifyObservers = function(){
angular.forEach(observerCallbacks, function(callback){
callback();
});
};
// initialize foo here
this.foo = '';
// register an observer
this.registerObserverCallback = function(callback){
observerCallbacks.push(callback);
};
}]);
HTML
You put the ng-view container outside of the body. It has to be inside. Also the path to a view starts with #/ so you have to change your links.
<!doctype html>
<html lang="en" ng-app="routeApp">
<head>
<script src="lib/angular/angular.js"></script>
<script src="lib/angular/angular-route.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
</head>
<body>
<li> ONE </li>
<li> TWO </li>
<!-- SinglePage -->
<div ng-view></div>
</body>
</html>
Each view only needs the content that should be placed inside the ng-view container. So you mustn't make a complete HTML document.
pat1.html
<h1> ONE </h1>
<button ng-click="handleClick"> BROADCAST </button>
<div ng-repeat="item in foo">{{ item }}</div>
pat2.html
<h1> TWO </h1>
<div ng-repeat="item in foo">{{ item }}</div>

Resources