Passing current tab url to server in angular resources fetch - angularjs

I am trying to send the current tab url to the resource service { in param } .
but the global tablUrl is not having any value at
var url = "http://[localhost]/getProfile?domain="+tabUrl
but getting logged corrent at :
console.log(tabUrl);
this is my code :
var tabUrl;
angular.module('jsonService', ['ngResource'])
.factory('JsonService', function($resource) {
chrome.tabs.getSelected(null, function(tab) {
tabUrl = tab.url;
console.log(tabUrl);
});
var url = "http://[localhost]/getProfile?domain="+tabUrl
return $resource(url,{}, {
list : {
method : 'GET',
cache : true
}
});
});
template binding :
<body ng-controller="extensionCtrl">
this is controller :
app.controller('extensionCtrl', function($scope , JsonService) {
JsonService.get(function(data){
$scope.data = data;
});
});

First:
Please, don't use the deprecated chrome.tabs.getSelected. Use chrome.tabs.query instead.
Second:
chrome.tabs.getSelected/chrome.tabs.query are asynchronous. This means that execution continues while they do some work in the background and the specified callback is called when they are done.
So, in a case like this:
line 1: chrome.tabs.getSelected(null, funkyCallback);
line 2: var url = ...
line 3: return $resource(...);
...a possible (and very probable) order of execution is:
1. chrome.tabs.getSelected (starts retrieving the active tab in the background)
2. line 2 gets executed (at this time 'tabURL' is not set yet)
3. line 3 gets executed (returning something)
4. Once the the active tab is retrieved, 'funkyCallback' is called
(setting 'tabURL' after it is too late).
When using asynchronous APIs (such as most of the chrome.* APIs), you have to change the whole logic of your scripts to be in line with the asynchronous nature of the API calls.
E.g., you could achieve the same result like this:
HTML:
<html ng-app="jsonService">
...
<body ng-controller="extensionCtrl">
<p>{{jsonData}}</p>
...
JS:
var app = angular.module("jsonService", ["ngResource"]);
app.factory("JsonFactory", function($resource) {
var url = "http://localhost/getProfile?domain=:tabUrl";
var retObj = $resource(url, {}, {
list: {
method: "GET",
cache: true
}
});
return retObj;
});
app.controller("extensionCtrl", function($q, $rootScope, JsonFactory) {
chrome.tabs.query({ active: true }, function(tabs) {
JsonFactory.list({ tabUrl: tabs[0].url }, function(data) {
// On success...
$rootScope.jsonData = data;
}, function(data) {
// On error...
$rootScope.jsonData = "Error using JsonFactory.list(...) !";
});
});
});
See, also, this short demo that does something similarly asynchronous

Related

AngularJS UI.router redirects to horrible url

I'm using angular-ui-router 1.0.3 and I'm trying to implement this url http://localhost:8888/details/2020?pending=true but when I type that url in the browser and hit enter when the page loads, automatically change the url to this http://localhost:8888/app/details/%7BParam:orderid%20%7BParamType:path%7D%20squash:%20'false'%20optional:%20false%7D?pending=%7BParam:pending%20%5Bobject%20Object%5D%20squash:%20%27false%27%20optional:%20true%7D
This is my app.config() code
$stateProvider.state('details',{
url:'/details/:orderid?pending',
name:'details',
templateUrl:'/views/details.html',
resolve:{
load:function($q, $rootScope){
var dfrd = $q.defer();
require(['/js/details.js'],function(){
dfrd.resolve();
$rootScope.$apply();
})
return dfrd.promise;
}
}
})
If I use $state.go({details:2020,pending:true}) from other views works perfect. The problem appears when I hit Enter in the URL
Also I'm getting this error in the console:
angular-ui-router.min.js:sourcemap:13 Transition Rejection($id: 0
type: 2, message: The transition has been superseded by a different
transition, detail: Transition#1( ''{} ->
'details'{"orderid":"{Param:orderid {ParamType:path} squash: 'false'
optional: false}"} ))
[SOLVED]
In my app.run() I had:
$transitions.onBefore({},function(event) {
var target = event._targetState._definition;
$rootScope.toState = target.name
$rootScope.toParams = target.params
if(target.name == 'signin') return true;
return auth.signin();
});
But all the problems were for use $rootScope inside the onBefore event. So the final code for my implementation is: (note the absence of $rootScope):
$transitions.onBefore({},function(event) {
var target = event._targetState._definition;
if(target.name == 'signin') return true;
return auth.signin({toState:target.name,toParams:target.params});
});
and this piece of code without changes:
$stateProvider.state('details',{
url:'/details/:orderid?pending',
name:'details',
templateUrl:'/views/details.html',
resolve:{
load:function($q, $rootScope){
var dfrd = $q.defer();
require(['/js/details.js'],function(){
dfrd.resolve();
$rootScope.$apply();
})
return dfrd.promise;
}
}
})

Angular V 1.3.15 $resource custom PUT configuration per documentation not working

this is the $resource configuration.
'use strict';
angular.module('MyApp')
.factory('Doc',['$resource',function DocFactory($resource){
return $resource('/db/doc/:dbName/:docId/:docRev',
null,
{'upDate': { method:'PUT' }}
);
}]);
DELETE and GET work fine
the upDate function is called with a submit button
$scope.upDate = function(){
Doc.upDate({dbName: 'lol-sched-teams',
docId: $scope.team._id,
docRev: $scope.team._rev})
.$promise.then(function (data) {
$scope.team = data;
});
}
When I debug into angular I find that the '/db/doc/' portion of the url is working fine but the ':docId/:docRev' are not being parsed to build out the entire url.
So at the Express server the request comes in as 'req: PUT /db/doc'
?????
Obviously I am missing SOMETHING!
Any help appreciated
Problem Solved???? Well understood anyway.
This is really not well documented. Happily the angular code is beautifully written and easy to follow.
$resource REALLY WANTS 4 arguments
params, data, function success(){}, function error(){}
If you debug into angular you will see this is the case on the parse of the command args
So I made the PUT work by re-coding the call to the resource factory to be:
Doc.upDate({dbName: 'lol-sched-teams',
docId: $scope.team._id,
docRev: $scope.team._rev},
$scope.team,
function success(data){
console.log(data);
},
function error(err){
console.log(err);
}
)
Within angular-resource this will now parse as
a1=params,
a2=data,
a3=success, // is A Function
a4=error // is A Function
This will be all gibberish unless you use the debugger and look at it running but when you do it will be perfectly obscure
'use strict';
angular.module('MyApp')
.factory('Doc',
[
'$resource',
function DocFactory($resource){
/*You must set de params of the resource*/
return $resource('/db/doc/:dbName/:docId/:docRev',
{
dbName : '#dbName',
docId : '#docId',
docRev : '#docRev'
},
{
upDate: {
method:'PUT',
url : '/db/doc/:dbName/:docId/:docRev' // can change
params: {
dbName : '#dbName',
docId : '#docId',
docRev : '#docRev'
}
}
}
);
}
]
);
....
/*First you must have a Doc resource*/
$scope.upDate = Doc.get({ // or $scope.upDate = new Doc();
dbName : 'someDbName',
docId : 'someDocId',
docRev : 'someDocRev'
}).$promise.then(
function(){
//$scope.upDate is now a Doc,
//Now you can call it here or in other event
$scope.upDate.$upDate({
dbName : 'newDbName',
docId : 'someDocId',
docRev : 'newDocRev'
}).then(
function(){
console.log("OK!")
}
).error(
function(){
console.log("UPS!")
}
);
}
);

angular $resource removes a property when object changes

I've created a Service that returns a $resource
module.registerFactory('Website', function ($resource, $cacheFactory) {
var cache = $cacheFactory('websites');
var pagedCache = $cacheFactory('websites_paged');
return $resource('/api/websites/:id', {id: '#id'}, {
query: {method: 'GET', isArray: false, cache: pagedCache},
get: {method: 'GET', cache: cache}
});
});
In an edit state I receive all details by calling
$scope.website = Website.get({'id': $stateParams.id});
The $scope.website promise contains my data as expected. (Below a shortened JSON result from server)
{"id":25,"name":"blabla","url":"http://here.com","description":"blabla",
"tags":[
{"id":6,"name":"..."},
{"id":7,"name":"..."}
{"id":10,"name":"..."}
],
"objectives":[
{"id":3206,"code":"WIS AD3.c","name":"[ommitted objective 3206]","parent_id":3203},
{"id":3209,"code":"WIS AD4.b","name":"[ommitted objective 3209]","parent_id":3207}
]}
My problem is with the objectives property.
In my EditCtrl I open a modal and send the objectives as selected items to the modal. That works perfect.
$scope.selectObjectives = function () {
var modalInstance = $modal.open({
templateUrl: 'app/modules/objectives/templates/select-objectives.html',
controller: 'SelectObjectivesModalCtrl',
size: 'lg',
resolve: {
selectedItems: function () {
return $scope.website.objectives;
}
}
});
modalInstance.result.then(function (selectedItems) {
$scope.website.objectives = selectedItems;
console.log($scope.website);
});
}
When closing the modal the newly selectedItems are injected back into $scope.website.objectives. (cfr. modalInstance.result.then() ... )
The console logs perfectly all properties - including the objectives.
Now comes the weird part:
As soon as I try to access $scope.website in another function (ie update)
The objectives property is removed from $scope.website.
This is my update method:
$scope.updateWebsite = function () {
console.log($scope.website);
$scope.website.$save(function () {
$cacheFactory.get('websites').remove('/api/websites/' + $scope.website.id);
$cacheFactory.get('websites_paged').removeAll();
$state.go('app.websites');
});
};
The console logs all properties in $scope.website - except for the objectives. This is completely removed.
I hope I made myself clear enough.
Thanks for taking some time to help me pointing to the right direction.
My bad.
My response didn't return the entire object as should be in a RESTful POST.

angularjs singleton doesn't work

In app.js I have a variable that I use in two files/controllers:
var app = angular.module('appDemo', ['MainControllers', 'MainServices'])
.constant('myConfig', {
'backend': 'http://localhost:1236'
})
.service('mailService', function() {
var mail = {
value: 'hello world'
};
var getMail = function() {
return mail;
}
var setMail = function(email) {
mail.value = email;
}
return {
getMail: getMail,
setMail: setMail
};
);
Setting the variable from controllerOne goes fine:
angular.module('MainControllers')
.controller('MemberController', function ($scope, mainService, appDemo) {
window.onbeforeunload = function (e) {
appDemo.setMail('test#test.com');
};
But when I get the setting variable from the controllerTwo than I get the default value:
angular.module('MainControllers')
.controller('EmailController', function($scope, appDemo) {
$scope.mailAddress = appDemo.getMail();
});
Each controller is in separate file.
what is wrong?
This may be because the service itself is being reloaded because as I can see you are setting the mail in the first controller on onbeforeunload.
Services can't persist on window reloads or page refresh. They get reloaded hence reinitialized every time you reload the page.
If you want to persist the values try putting it in localStorage or sessionStorage.

Angular resource (ngResource) won't make the AJAX call when called inside a function

I'm trying to make an AJAX call with ngResource, In the code below 'a' and 'b' both print, but the AJAX call from Table.import() does not get made. If I move the AJAX call outside of onFileRead, then it works. What could be the problem?
var TableImportController = ['$scope','Table', 'project', 'table',
function($scope, Table, project, table) {
$scope.table = table;
$scope.project = project;
$scope.onFileRead = function(file) {
console.log('a');
Table.import({ data : file.data}, function() {
}, function() {
});
console.log('b');
};
}];
Where Table is an ngResource
.factory('Table', function($resource) {
var Table = $resource('/api/tables/:id:listAction/:itemAction',
{
id: '#id',
listAction: '#listAction',
itemAction: '#itemAction'
},
{
update: { method: 'PUT' },
import : { method: 'POST', params: { listAction: 'import' }},
}
);
return Table;
});
You are declaring $scope.onFileRead as a function.
What is calling onFileRead?
When you move the call outside of the function, it is being run as part of initialization.
What provides the input file?
Probably bind to the onFileRead function from something in your DOM.
I figured it out. It looks like I ran into this bug: https://github.com/angular/angular.js/issues/2794#issuecomment-18807158.
I solved the issue by wrapping the AJAX call (and eventually moved it to where the onFileRead callback is triggered) in a scope.$apply(function() { });

Resources