So, this is my HTML.
<input type="text" id="ghusername" ng-model="username" placeholder="Github username...">
<span id="ghsubmitbtn" ng-click="getUsers()">Pull User Data</span>
This is my Controller A.
app.controller("homeController", ["$scope", "$http", function ($scope, $http) {
$scope.getUsers = function () {
$http.get("https://api.github.com/users/" + $scope.username)
.success(function (data) {
//some stuff
})
And this is B (for posting sake). How do I get this username on the HTML ngModel, so that I can show it in another controller? ex:
app.controller("reposController", ["$scope", "$http", function ($scope, $http) {
$scope.getRepos = function () {
$http.get("https://api.github.com/users/" + $scope.username + "/repos")
.success(function (data) {
// some stuff
})
};
I've tried to user services, factories and even $rootScopes, but they just don't seem to work, any help? Btw, if I wasn't clear tell me and I will edit the post, Thank you.
EDIT: I ended up using $rootScope, I know it isn't the best idea but it was a minor thing. I'll keep all your answers for reference tho, as I'm sure they all work but I'm just too dumb to implement them.. Thank you.
You must to refernce $rootScope into your controllers:
app.controller("homeController", ["$scope", "$http","$rootScope", function ($scope, $http, $rootScope) ...
and after that just access rootscope variables:
controller1: $rootScope.someValue = "some value";
Controller2: $scope.controllerScopeValue = $rootScope.someValue;
Use service
app.service('name', [function(){}])
Then add 'name' to both the controllers like
app.controller("reposController", ["$scope", "$http", 'name', function ($scope, $http, name) {
$scope.name = name;
Then you can access it like
name.username
and in html
<input type="text" id="ghusername" ng-model="name.username" placeholder="Github username...">
Try something like this
http://jsfiddle.net/devkickstart/nevyhdn0/2/
Using a factory you can share the data between controller like so...
<div ng-app="myApp">
<div data-ng-controller="reposCtrl">
<input type="text" id="ghusername" ng-model="username" placeholder="Github username..." ng-init="getRepos()" />
{{data}}
</div>
<div data-ng-controller="homeCtrl"> <span id="ghsubmitbtn" ng-click="getUsers()">Pull User Data</span>
{{otherData}}
</div>
</div>
angular.module("myApp", [])
.factory("dataFact", ["$rootScope", function ($rootScope) {
var myData = "value from factory";
return {
getData: function () {
return myData;
},
setData: function (newVal) {
this.myData = newVal;
}
}
}]).controller("homeCtrl", ["$scope", "dataFact", function ($scope, dataFact) {
$scope.getUsers = function () {
$scope.otherData = dataFact.getData();
}
}]).controller("reposCtrl", ["$scope", "dataFact", function ($scope, dataFact) {
$scope.getRepos = function () {
$scope.username = dataFact.getData();
}
}]);
With some assumptions about your data model, this should work.
It creates a shared singleton object. One controller adds the user (or whatever data) as an attribute of that. Then other controllers, or indeed the same controller if it is reloaded, can then access the same data on shared.
Note here that a service just returns a singleton of anything, it doesn't need code or methods. In this case, it's easier to use a value instead which is shorthand for function() { return {}; } and works just as well.
Remember to inject shared wherever it is needed.
app.controller("homeController", ["$scope", "$http", "shared", function ($scope, $http, shared) {
$scope.getUsers = function () {
$http.get("https://api.github.com/users/" + $scope.username)
.success(function (data) {
shared.user = data.user; // or wherever it comes from
//some stuff
})
app.controller("reposController", ["$scope", "$http", "shared", function ($scope, $http, shared) {
$scope.getRepos = function () {
$http.get("https://api.github.com/users/" + shared.user.name + "/repos")
.success(function (data) {
// some stuff
})
};
app.value('shared', {});
Related
I would like to ask you if it is possible, and if yes, then how can I pass some variable from controller to directive.
Here is a bit of my code:
app.js
var VirtualGallery = angular.module('virtualGallery', ['VirtualGalleryControllers', 'ngRoute']);
VirtualGallery.constant('apiURL', 'roomPicture');
VirtualGallery.run(['$rootScope', function ($rootScope) {
$rootScope.roomPictures = [];
}]);
var VirtualGalleryControllers = angular.module('VirtualGalleryControllers', ['ngRoute']);
VirtualGalleryControllers.controller('AppCtrl', function ($http, $rootScope, $scope, apiURL, $q) {
$scope.getallrooms = function () {
$http.get(apiURL)
.success(function (data) {
$rootScope.roomPictures = data; //idk whether to use $scope or $rootScope
});
};
});
In this app.js I'm trying to get some data from DB, and that data I need to use in directive.
Directive
angular.module('virtualGallery')
.directive('ngWebgl', function () {
return {
restrict: 'A',
scope: {
'getallrooms': '=',
'roomPictures': '='
},
link: function postLink(scope, element, attrs) {
scope.init = function () {
//here I would like to be able to access $scope or $rootScope from app.js file.
};
}
};
});
In directive I need to gain access to $scope or $rootScope in function init() where I need to use that data.
HTML
<body ng-app="virtualGallery">
<div class="container" ng-controller="AppCtrl">
<div
id="webglContainer"
ng-webgl
getallrooms="getallrooms"
roomPictures="roomPictures"
></div>
<p ng-model="roomPictures"></p>
<p ng-model="getallrooms"></p>
</div>
<script type="text/javascript" src="js/vg.js"></script>
<script type="text/javascript" src="js/ngWebgl.js"></script>
In html I'm trying to pass that data from app.js to directive.
Im quite new to Angular and this is even my first directive, so I am bit confused. Every help will be appreciated. Thanks guys :)
In your app.js use the controller like this
VirtualGalleryControllers.controller('AppCtrl', function ($http, $rootScope, $scope, apiURL, $q) {
$scope.getallrooms = function () {
$http.get(apiURL)
.success(function (data) {
$scope.roomPictures = data; //use $scope instead of $rootScope
});
};
});
Then for your directive:
angular.module('virtualGallery')
.directive('ngWebgl', function () {
return {
restrict: 'A',
scope: {
pictures: '=virtualGallery'
},
link: function postLink(scope, element, attrs) {
scope.init = function () {
// you can access the variable through the scope
scope.pictures;
};
}
};
});
Or you could simply make the http request in your directive and manipulate the data there.
You can inject $rootScope to your directive ( like you did in your controller ) and then access that rootScope variable.
I couldn't pass the parameter from angular controller to factory. Can any one help me on this? It works without passing parameter but when I pass it it's not.
var app = angular.module('employee', ['ui.grid', 'ui.grid.saveState', 'ui.grid.selection', 'ui.grid.cellNav', 'ui.grid.resizeColumns', 'ui.grid.moveColumns', 'ui.grid.pinning', 'ui.bootstrap', 'ui.grid.autoResize','ui.grid.pagination']);
app.controller('EmpCtrl', ['$scope', '$http', '$interval', '$modal', '$log', 'gridService', function ($scope, $http, $interval, $modal, $log, gridService) {
$scope.LoadNextPage = gridService.LoadNextPage("5");
}]);
var gridService = function ($http, $rootScope) {
return {
LoadNextPage: function (hh) {
alert(hh);
},
gridOptions:gridOptions
};
};
app.factory('gridService', ['$http', '$rootScope', gridService]);
And this is how I use it in the view
<span id="pcNext"
class="glyphicon glyphicon-step-forward"
ng-click="LoadNextPage()">
</span>
The problem is in your controller:
$scope.LoadNextPage = gridService.LoadNextPage("5");
This means that your LoadNextPage is not a function but rather a result of the call to a function in your service. Which btw doesn't return anything but rather just displays an alert. But in your view, you're using LoadNextPage as a function call...
Change it to this so your controller's LoadNextPage will be a function that you can call from the view.
$scope.LoadNextPage = gridService.LoadNextPage;
and in your view:
<span id="pcNext"
class="glyphicon glyphicon-step-forward"
ng-click="LoadNextPage(5)">
</span>
This should work.
Note: I suspect that your gridOptions are defined somewhere outside of scope of your code that you provided in the question so that it doesn't throw and error because of the missing (likely) object. So I considered this a typo in your code and not the actual problem.
Don't want params in your view?
No problem. You can either create a wrapper function or bind it to specific parameters in your code:
// wrap
$scope.LoadNextPage = function() {
return gridService.LoadNextPage("5");
};
// bind
$scope.LoadNextPage = gridService.LoadNextPage.bind(this, 5);
Or bake the number in your service...
Issue here is gridOptions:gridOptions is not defined which throws error.
Remove ,gridOptions:gridOptions from factory.
Check snippet for working code and compare with your code.
var app = angular.module('employee', []);
app.controller('EmpCtrl', ['$scope', 'gridService', function ($scope, gridService) {
$scope.clickMe = function() {
$scope.LoadNextPage = gridService.LoadNextPage("5");
}
}]);
var gridService = function() {
return {
LoadNextPage: function (hh) {
alert(hh);
}
};
};
app.factory('gridService', ['$http', '$rootScope', gridService]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="employee" ng-controller="EmpCtrl">
<button ng-click="clickMe()">Button</button>
</div>
you not defined gridOptions function see this link:
angular.module("myApp", []).controller("myCon", function($scope, $interval, gridService){
$scope.LoadNextPage = gridService.LoadNextPage("5");
}).factory('gridService', ['$http', '$rootScope', gridService]);
function gridService($http, $rootScope){
return {
LoadNextPage: function (hh) {
alert(hh);
}
};
}
see this link
I have school task.
We have a HTML code like this:
<html ng-app="myTest">
<head><script type="text/javascript" src="../myScript.js"></script>
</head>
<body id="tst" class="textpage" ng-controller="TestController as testcon">
<form class="" id="frm" ng-submit="doStuff()">
<div class="form-group">
{{testinfo}}
</div>
<div class="form-group">
<button type="submit" id="sbtn" name="sbtn">testSubmit</button>
</div>
</form>
</body>
</html>
Content of javascript with name myScript.js is this:
var tester = angular.module('myTest', ['ui.mask']);
tester.controller('TestController', ['$scope', '$http', '$location', '$window', function ($scope, $http, $location, $window) {
$scope.doStuff = function () {
{
$scope.testinfo = 'unknown value';
};
};
}
]);
I have option to add new javascript.
But I am not possible to get value from $scope.testninfo.
I cannot edit existing JavaScript and cannot edit HTML file. I can just add new javascript.
Is there option how to get value from $scope.testinfo in another javascript?
Thanks.
You can use broadcast
From controller 1 we broadcast an event
$scope.$broadcast('myEvent',anyData);
controller 2 will receive our event
$scope.$on('myEvent', function(event,anyData) {
//code for controller 2
});
here anyData represent your object to be passed
Use ng-model.
<div class="form-group">
<input type="text" ng-model="testinfo">
</div>
I dont think it is possible without appending the existing javascript/html. Because the $scope of the TestController cannot be accessed from another controller (file).
If you COULD append the HTML you could use the $rootscope, in that way the value, which is set by the TestController is accessible from another controller. Or you can add a Global app value. I created a fiddle which show the two options: https://jsfiddle.net/Appiez/wnyb9pxc/2/
var tester = angular.module('myTest', []);
tester.value('globalVar', { value: '' });
tester.controller('TestController', ['$rootScope', '$scope', '$http', '$location', '$window', 'globalVar', function ($rootScope, $scope, $http, $location, $window, globalVar) {
$scope.doStuff = function () {
{
$rootScope.testinfo = 'this is the new value';
globalVar.value = 'a global value';
};
};
}
]);
tester.controller('TestController2', ['$rootScope', '$scope', 'globalVar', function ($rootScope, $scope, globalVar) {
$scope.doStuff2 = function () {
{
alert($rootScope.testinfo);
alert(globalVar.value);
};
};
}
]);
This is what services are for in angular. They ferry data across controllers. You can use NG's $broadcast to publish events that contain data, but Providers, Services, and Factories are built to solve this.
angular.module('krs', [])
.controller('OneCtrl', function($scope, data){
$scope.theData = data.getData();
})
.controller('TwoCtrl', function($scope, data){
$scope.theData = data.getData();
})
.service('data', function(){
return {
getData: function(){
return ["Foo", "Bar"];
}
}
});
Here's a fiddle to help get you into the swing of things. Good luck in school!
I have an app based on Angular which I initialize like this:
myapp.init = (function () {
'use strict';
var angularApp = angular.module('myapp', [])
.directive('homeIterationDirective', function () {
return function (scope, element, attrs) {
var isTopCard = scope.$last ? true : false;
cards.initSingleSwipe(element.get(0), function (event) {
// I want to call indexPageController.onSwiped(event) here!
}, isTopCard);
};
})
.directive('homeDirective', function () {
return function (scope, element, attrs) {
cards.initPanel(element, function (event) {
// I want to call indexPageController.onButtonPressed(event) here!
});
};
});
angularApp.factory('AjaxService', myapp.services.AjaxService);
angularApp.controller('IndexPageController', ['$scope', '$http', '$sce', 'AjaxService', myapp.pages.IndexPageController]);
}());
My controller looks like this:
myapp.pages.IndexPageController = function ($scope, $http, $sce, MyService) {
'use strict';
var somevalue = {};
this.onSwiped = function (event) {
doSomethingWith(event, somevalue);
};
this.onButtonPressed = function (event) {
doSomethingWith(event, somevalue);
};
};
In the 2 directives homeIterationDirective and homeDirective I have 2 callbacks cards.initSingleSwipe and cards.initPanel. Within these callbacks I want to call public methods of my controller but I don't have the instance available that Angular created from IndexPageController. How can I achieve this?
Use (inject) a service (and not a Controller) if you want "to call a public method" from another place, possibly from another Controller.
angularApp.controller('MyController', function ($scope, IndexPageService) {
IndexPageService.blah();
}));
Controller is intended to receive and modify a $scope (adding methods, variables..etc). The $scope can than be used inside the template (html) that use the controller itself.
If you want to call some controller code within the Angular context but in another place, then you should probably move that calling code to a service and then call the service method directly.
But if you want to call that method outside Angular context then, you can achieve that like this:
<div id="foo" ng-controller="IndexPageController">
<!-- code -->
</div>
Now, you can write something like this:
angular.element(document.getElementById("foo")).scope().blah();
I also think you should use a service for this. But if you still need to call one controller from another you can use $controller service
(function() {
var app = angular.module('myApp', ['ngRoute']);
app.config(function ($routeProvider) {
$routeProvider.when("/first", {
templateUrl: 'app/view.html',
controller: 'firstCtrl'
}).when("/second", {
templateUrl: 'app/view.html',
controller: 'secondCtrl'
})
.otherwise({
redirectTo: "/first"
});
});
app.controller('firstCtrl', function ($scope) {
$scope.name = "first Controller";
$scope.nameToUpper = function () {
return $scope.name.toUpperCase();
}
});
app.controller('secondCtrl', function ($scope, $controller) {
var newScope = $scope.$new();
$controller('firstCtrl', { $scope: newScope });
$scope.name = newScope.nameToUpper() + 'from second ctrl';
});
}())
and view is
<div>
{{name}}
</div>
Im trying to use a factory in angularJS, but I don't work as expected.
Here is my controller:
as.controller('Test', ['testFactory', function($scope, $http, $rootScope)
{
$http.get($rootScope.appUrl + '/nao/test/test')
.success(function(data, status, headers, config) {
$scope.test = data;
});
$scope.form = {};
$scope.submitForm = function(isValid) {
if(isValid)
{
testFactory.testFactoryMethod(function($http) {
$scope.test = data;
});
}
};
}]);
As you can see, I "include" my factory to the controller.
Here is my factory:
.factory('testFactory', function($http) {
return {
testFactoryMethod: function(callback) {
return $http('http://127.0.0.1:81/test/test', data).success(function(data) { callback(data);
});
}
};
});
When I run this, I get this error message:
Error: $http is undefined
#http://127.0.0.1:82/nao/js/controllers.js:82:3
Anyone who can help me?
This happens because of Angular $injector. When you provide an array as 2nd argument for .controller, the $injector tries to find all dependencies listed on it by their name and then inject them to the array's last element (which must be a function), so in your case, this is what happens:
'testFactory' -> $scope
undefined -> $http
undefined -> $rootScope
Your code should be either like this:
as.controller('Test', ['$scope', '$http', '$rootScope', 'testFactory', function($scope, $http, $rootScope, testFactory)
{
// ...
... or like this:
as.controller('Test', function($scope, $http, $rootScope, testFactory)
{
// ...
Edit: As #sp00m stated, the second example should not be used if you are going to uglify (minify) your code, because the uglifier algorithm will replace those identifiers with something like:
function(a, b, c, d)
And then AngularJS will not be able to find those dependencies anymore, whereas the first example would look like this:
['$scope', '$http', '$rootScope', 'testFactory', function(a, b, c, d)
Which is valid, because you are explicitly telling Angular which dependencies it must inject.
There is a problem with the dependencies in your controller. The names you have as strings in the array don't match the arguments to your factory function.
This should work:
as.controller('Test', ['$scope', '$http', '$rootScope', 'testFactory', function($scope, $http, $rootScope, testFactory)
{
$http.get($rootScope.appUrl + '/nao/test/test')
.success(function(data, status, headers, config) {
$scope.test = data;
});
$scope.form = {};
$scope.submitForm = function(isValid) {
if(isValid)
{
testFactory.testFactoryMethod(function($http) {
$scope.test = data;
});
}
};
}]);
I think you're forgetting the $http.post:
$http(url, data) should be $http.post(url, data)
And what others have said before, you need the testFactory injected in the controllers function.
You should declare your controller like this
as.controller('Test', ['$scope', '$http', '$rootScope', 'testFactory', function($scope, $http, $rootScope, testFactory)
{
....
}