I am creating a variable rejecting another one, in "First.js" file:
var nosubs = _.reject(subs, function (bi) { return bi.ParentBoardbookItemId === '0'; });
Is it possible to call this variable (nosubs) to "Second.js" file?
How can I do that?
Notice that i a
Thank you in advance!
There is tons of way of doing it. The best in angular is to not use variables. But to store your data in a service.
// simplified version of defining the service
app.service("myService", function(){
this.setData = function(data){
this.data = data;
};
this.getData = function(){
return this.data;
};
return this;
});
// now you just have to inject it in your controllers/run blocks and you can use myService.data.
Another solution would be to store it in the $rootScope.
If you want/need something else we'll need more information.
You can store varible in rootscope to access in other files.
$rootScope.nosubs = _.reject(subs, function (bi) { return bi.ParentBoardbookItemId === '0'; });
Related
How to How to write function in controller which returns some value or object ?
like
$scope.getTwoNumber=function(){
var num1=9;
var num2=10;
var obj={first:num1,sec:num2}
return obj;
}
$scope.someOtherFunc=function(){
var numbers={};
numbers=$scope.getTwoNumber()
}
how to achieve it?
You can write a function in controller. Example:
myApp.controller('thisController', function($scope){
$scope.thisValue = false;
function myFunction(){
console.log('from this function');
return true;
}
$scope.thisValue = myFunction();
});
Make sure you don't forget the ";" sign at the end of the function call. The rest seems fine to me. Note you have to declare the object $scope and make sure it's not empty.
For detailed information about Controllers, please read: http://php-html.net/tutorials/model-view-controller-in-php/
$scope.someOtherFunc(){
var numbers={};
numbers=$scope.getTwoNumber();
}
Recently it has become possible to use angularjs within google apps script via the iframe sandbox mode.
My problem comes when trying to communicate with the server (gapps spreadsheet) and receiving asynchronous data in return.
The implementation for receiving data from the server is to use a function with a callback function like so:
google.script.run.withSuccessHandler(dataGatheringFunction).getServerData();
getServerData() would be a function that resides server-side that would return some data, usually from the accompanying spreadsheet. My question is how to use the callback function within the parameters of AngularJS. A typical $http function could be placed in a provider, and the scope value could be populated after then.() returns. I could also invoke $q. But how would I deal with the necessity of google's callback?
Here's a simplified version of what I'm messing with so far:
app.factory("myFactory", function($q){
function ssData(){
var TssData = function(z){
return z;
}
google.script.run.withSuccessHandler(TssData).getServerData();
var deferred = $q.defer();
var d = deferred.resolve(TssData)
console.log("DP: " + deferred.promise);
return deferred.promise;
}
return ssData();
})
Then in the controller resolve the server call similar to this:
myFactory.then(set some variables here with the return data)
My question is simply - How do I deal with that callback function in the provider?
The script throws no errors, but does not return the data from the server. I could use the old $timeout trick to retrieve the data, but there should be a better way.
You only need to $apply the output from the server function:
google.script.run.withSuccessHandler(function(data) {
$scope.$apply(function () {
$scope.data = data;
});
}).withFailureHandler(errorHandler).serverFunction();
Maybe the most elegant solution that makes sure the google.script.run callbacks are registered automatically in the AngularJS digest cycle would be to use the $q constructor to promisify the google callbacks. So, using your example above:
app.factory('myFactory', ['$q', function ($q){
return {ssData: ssData};
function ssData(){
var TssData = function(z){
return z;
};
var NoData = function(error) {
// Error Handling Here
};
return $q(function(resolve, reject) {
google.script.run
.withSuccessHandler(resolve)
.withFailureHandler(reject)
.getServerData();
}).then(TssData).catch(NoData);
}
}]);
Then in your controller you can call myFactory.ssData()
Since I don't know exactly what TssData is doing I included it here but note that this simply returns another promise in this context which you will still have to handle in your controller:
myFactory.ssData().then(function(response) {
// Set data to the scope or whatever you want
});
Alternately, you could expose TssData by adding it to the factory's functions if it is doing some kind of data transformation. If it is truly just returning the response, you could refactor the code and omit TssData and NoData and handle the promise entirely in the controller:
app.factory('myFactory', ['$q', function ($q){
return {ssData: ssData};
function ssData(){
return $q(function(resolve, reject) {
google.script.run
.withSuccessHandler(resolve)
.withFailureHandler(reject)
.getServerData();
});
}
}]);
app.controller('myController', ['myFactory', function(myFactory) {
var vm = this;
myFactory.ssData()
.then(function(response) {
vm.myData = response;
}).catch(function(error) {
// Handle Any Errors
});
}]);
An excellent article about promises (in Angular and otherwise) is here: http://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html
This guy seems to be pulling data from a GSheet into angular quite happily without having to do anything fancy.
function gotData(res) {
$scope.validUser = res.validUser;
var data = angular.copy(res.data), obj, i=0;
Object.keys(data).forEach(function(sh) {
obj = {title: sh, checked: {}, showFilters: false, search: {}, sort: {index: 0, reverse: false}, currentPage: 0, checkedAll: true, showBtns: true, searchAll: ''};
obj.heading = data[sh].shift();
obj.list = data[sh];
obj.heading.forEach(function(s,i) {
obj.checked[i] = true;
});
$scope.sheets.push(obj);
});
$scope.sheets.sort(function(a,b) {
return a.title > b.title ? 1 : -1;
});
$scope.gotData = true;
$scope.$apply();
}
google.script.run.withSuccessHandler(gotData).withFailureHandler($scope.gotError).getData();
My solution was to get rid of the $q, promise scenario all together. I used $rootScope.$broadcast to update scope variables from the server.
Link to spreadsheet with script.
I am trying to set up a middle ground between modules to get a custom url so that the user may save (copy the url) the state and share it with other users (or return to it). I am trying to build a simple working copy, then my goal is to make it as polymorphic as possible.
I have a basic working copy right now using a url object to store some variables (in the url object right now), which are then read in the controllers on load to change to the desired state. For example, the very top of my first controller is
$scope.test = $location.search().test;
so whatever test= in the url, it will set to $scope.test (these control my state). I have everything broken out into individual modules right now, so my initial method of getting the modules to speak is setting a function like this (found elsewhere on stack)
function persistMod($scope, $window) {
$scope.$watch(function (){
return $window.test;
}, function(v) {
if(v == undefined ){}else{
if($scope.test !== v) {
$scope.test = v;
}
}
});
$scope.$watch('test', function(v) {
if($window.test !== v) {
$window.test = v;
}
});
$scope.$watch(function (){
return $window.test2;
}, function(v) {
if(v == undefined ){}else{
if($scope.test2 !== v) {
$scope.test2 = v;
}
}
});
$scope.$watch('test2', function(v) {
if($window.test2 !== v) {
$window.test2 = v;
}
});
}
And in the controllers I just call
persistMod($scope, $window);
The purpose of this is to let them keep track of each other separately so when the url is updated - each module can keep track of the other ones current state so there is no confusion. So I can call
$location.search({mod1: $scope.test, mod2: $scope.test2});
When the state changes in each and it will stay the same.
So the problem here is - I would like to turn this into a service I can inject into both modules as an in between to keep track of this for me and change the url accordingly. So I'm wondering is this more of a factory or a service's job.
I want to :
-keep track of how many states change (lets say there can be a min of 2 and a max of 15) and change the url accordingly
-be able to send the new url individually for each module and have it update the url string with kind of a post to the service like myService.urlChange("newurlvariable");
So the factory/service would have to keep track of how many modules are using it and change accordingly. This is still new to me so I could use some guidance, I've done a bunch of digging around and feel stuck right now. Any insight is more than welcome. Thanks for reading!
So you definitely want a factory for this. But you will need to rewrite most of this to do what you want.
It's important to think of factories as a singleton, almost like global functions and variables. You could have a factory like this...
app.factory('PersistMod', [
function() {
var service = {};
service.url;
service.addItem = function(item) {
service.url = service.url + item;
}
service.getUrl = function() {
return service.url;
}
return service;
}])
I won't write our the whole thing but hopefully this will give you an idea on how to set it up.
Once this is setup you can inject this factory into your controller and then call the functions or get the variables. For example
PersistMod.addItem('something');
var currentUrlString = PersistMod.getUrl;
console.log(currentUrlString) // 'something'
Hopefully that helps.
Something like that?
angular.module(...).factory('persistMod', function ($window) {
return function persistMod($scope, name) {
//watch $window[name]
//watch $scope[name]
}
});
[...]
angular.module(...).controller('MyCtrl', function($scope, persistMod) {
persistMod($scope, 'test');
persistMod($scope, 'test2');
});
Also, why not simplify this:
if($window.test !== v) {
$window.test = v;
}
...with this:
$window.test = v;
No need to test before assigning.
I have the following service:
myApp.service('myService', function(){
this.functionOne = function(){
return true;
};
this.functionTwo = function(){
// Call functionOne
};
});
I would like to call functionOne from functionTwo without having to rewrite the way the service is written (in this case, returning an object with functions).
Is there a way to do this using the this format of providing functions?
There are multiple ways to do this, but the safest is to just define a _this variable.
myApp.service('myService', function(){
var _this = this;
this.functionOne = function(){
return true;
};
this.functionTwo = function(){
var x = _this.functionOne();
};
});
In this case the variable _this references the myService object that is created by AngularJS.
The problem here is that this is a JavaScript special variable that can be assigned values. It doesn't work like it does in other languages. So unless you know what the this variable will be at the time of the closure functions execution you should just use a variable you know is safe.
app.factory('myService', function() {
var firstFn = function() {
secondFn();
//some code
}
var secondFn = function() {
//additional code
}
return {
firstFn: firstFn;
}
})
This code exposes the firstFn to wherever this service gets called. When you call firstFn, it will also run secondFn. You can access firstFn using myService.firstFn() whenever you inject this service. Hope that helps.
Note: I've used a factory instead of a service. There's a subtle yet significant difference between the two. Long story short, a factory is a bit more flexible than a service with respect to what you can do with it.
Two Important Notes:
1. My goal is to AVOID using $scope in this case since it's my understanding that impedes the new "controller as" syntax.
2. My problem is likely a variable scope issue and so perhaps just clarifying the proper JS way might solve the problem.
Nevermind the exports, I'm working with browserify in my workflow.
I have this working code:
exports.IntroCtrl = function($scope, $http) {
$scope.introData = [];
$http.get('data/intro.json')
.success(function(res){
$scope.introData = res;
});
};
That ideally I'd like to work as something like this, for the sake of using the "controller as" syntax.
exports.IntroCtrl = function($http) {
this.introData = [];
$http.get('data/intro.json')
.success(function(res){
introData = res;
});
};
The problem is that the $http service seems to be executing before my initial this.introData declaration since I get a variable not defined error.
If tell this.introData = $http.get… then it returns an array of 5 objects that I can't access and intro.json only contains 4.
Thanks for any guidance/help.
First of all create a service for the http call. It is very convenient way to get the callback in the controller and then assign your controller as variables. Here is the factory for you:
Factory
app.factory('getDataService',function ($http) {
return {
getData:function(callback){
$http.get('data/intro.json')
.success(callback)
});
}
}
});
In your controller you get inject the getDataService and bind the data like this:
Controller:
app.controller('testController',['getDataService',function(testDataService){
this.introData = [];
testDataService.getData(function(data){
this.introData = data;
});
}]);
Here you need to bind the introData of the controller function.
You have to remember this variable that reference the controller instance, and use it later in the success callback like this:
exports.IntroCtrl = function($http) {
this.introData = [];
var ctrl = this; // remember 'this', the controller instance, to use in the success callback below
$http.get('data/intro.json')
.success(function (res) {
ctrl.introData = res;
});
};
Hope this helps.