Internet explorer 11 Angularjs + NodeJS + Mongoose issue - javascript

I'm developping my website with Angularjs framework in the front end , nodejs backend and mongoose to persist my data into a MongoDB database.
In firefox RS v.24 and chrome all is ok, when i add a user into the database, this new user is displayed automatically into my list grid.
But in IE 11 it doesn't until i close the browser and open it back .
when i add a new profile, i do the following in my Controller:
$scope.AddProfil = function() {
$http.post('/ajouterProfils', $scope.profil)
.success(function(data) {
$scope.profilFlag = data; /*unit tests*/
$scope.lastDocId = data._id;
$scope.ajouterProfilTag($scope.lastDocId);
$scope.profil = {};
$scope.tagStyles.length = 0;
$scope.tagStyles = [];
$scope.colorList = {};
angular.element($('.shown-text-add').text($('.shown-text-add').text()));
angular.element($('.shown-text-add').css('font-family', ''));
angular.element($('.shown-text-add').css('font-size', ''));
angular.element($('.shown-text-add').css('line-height', ''));
angular.element($('.shown-text-add').css('font-weight', ''));
setTimeout( function(){$('#addPanel').show();} );
setTimeout( function(){$('#addPanel').fadeOut();}, 2500);
});
};
in my DAO, i have this :
/**
* Add a profile
*/
exports.createProfile = function(req, res) {
var profile = new Profil(req.body);
profile.save(function(err) {
if (err) {
return res.send('users/signup', {
errors: err.errors,
profile: profile
});
} else {
res.jsonp(profile);
}
});
};
Any ideas ? feedbacks ?

As commented, use directives and data binding rather than DOM manipulation.
Clearly this is your problem as you say the data is there when you reload the browser, so the issue is not with the server side components.

Related

Working with nodejs api

I'm new to nodejs and this is my first app. I am trying to use a nodejs API called event registry to get some data. Implementation below:
app.get('/eventregistry', function(req,res){
console.log("dfsdfdf");
var er = new erBase.EventRegistry({apiKey: "API Key"});
er.getConceptUri("syria").then((conceptUri) => {
var q = new erBase.QueryArticlesIter(er, {conceptUri: conceptUri, sortBy: "date"});
q.execQuery((items) => {
for(var item of items) {
console.info(item);
}
})
});
});
My problem is when I run the server and go to the route nothing happens. My event package is installed and required as well. What am I doing wrong?
you must send a response back to client using that res object in your callback function:
app.get('/eventregistry', function(req,res){
console.log("dfsdfdf");
var er = new erBase.EventRegistry({apiKey: "API Key"});
er.getConceptUri("syria").then((conceptUri) => {
var q = new erBase.QueryArticlesIter(er, {conceptUri: conceptUri, sortBy: "date"});
q.execQuery((items) => {
for(var item of items) {
console.info(item);
}
res.status(200).json(items); // as example
})
});
});
I highly recommend you reading express documentation, exceptionally their Response Object part.

angularjs service doesn't work fine when call for API?

I was working with a angular project that include controllers and services. problem comes out from the codes following:
qrcodeCtrl.js
angular
.module('Admin',['ngResource'])
.controller('qrcodeCtrl',function($scope,qrcodeservice,statusservice){
$scope.init = function(){
$scope.getQrcodes();
}
$scope.getQrcodes = function(){
qrcodeservice.getQrcodes()
.then(function(res){
$scope.qrcodes = qrcodeservice.qrcodeList;
$scope.loginstatus = [];
var logininfo = [];
for(var i = 0; i < $scope.qrcodes.length; i++){
logininfo[i] = self.setInterval(getloginfo,10000,i);
}
function getloginfo(i){
uuid = $scope.qrcodes[i];
statusservice.getstatus(uuid).then(function (result) {
console.log(uuid+" "+result.code);
uuid = result.uuid;
switch(result.code){
case 201 : $scope.loginstatus[uuid] = 'login ...';break;
case 200 : $scope.loginstatus[uuid] = 'login success';window.clearInterval(logininfo[i]);break;
case 500 : $scope.loginstatus[uuid] = 'login fail';window.clearInterval(logininfo[i]);break;
default : $scope.loginstatus[uuid] = 'waitting';break; //code 408
}
},function (err) {
console.log(err);
})
return;
}
},function(err){
console.log(err);
})
}
$scope.init();
})
statuservice.js
angular
.module('Admin',['ngResource'])
.service('statusservice',function ($http,$q) {
var auth = this;
auth.getstatus = function(uuid){
var defer = $q.defer();
// //debug
// var code = 200;
// var result = {"uuid":uuid,"code":code};
// defer.resolve(result);
// return defer.promise;
// //=================
$http.get("/check?uuid="+uuid)
.success(function(code){
res = {"uuid":uuid,"code":code};
defer.resolve(res);
})
.error(function(err,status){
console.log(err);
defer.reject(err);
})
return defer.promise;
}
})
about the codes, the service is for getting login info from API which test work fine. and the controller set a interval for getting login info from service constantly. When it turn out login success(200) or login fail (500), the interval will stop. those codes work for login section of a project.
When service doesn't get the login code from API and just write the code, (comment section)the service work fine , the code is 200 and the interval stop, alse view render fine.
But when service get the login code from API, the interval doesn't stop. and from the chrome console , i find out that the code is success change to 200, but still loop the interval. and the view doesn't render to login success.
I was learning angular for few days, could someone tell me why that happen??
your module declaration and usage is incorrect
angular.module('Admin',['ngResource']).something should not be done;
this initialize module admin every time.
you should declare in the below format
var app = angular.module('Admin',['ngResource']);
angular
.module('Admin')
.service('statusservice',function ($http,$q) {
});
angular
.module('Admin')
.controller('qrcodeCtrl',function($scope,qrcodeservice,statusservice){
});

Safari: IndexedDB: Cannot create object stores in separate transactions

It appears that the Safari and iPhone web browsers are incapable of allowing the user to create different object stores from separate transactions. This is even the case when the user closes the database, increments the version number and then uses createObjectStore() within the onupgradedneeded callback.
Is there a workaround?
For example, visit http://bl.ocks.org/redgeoff/1dea140c52397d963377 in Safari and you'll get an alert with the "AbortError" when Safari attempts to create the 2nd object store.
For convenience, here is the same snippet of code:
var idb = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB
|| window.msIndexedDB;
// Generate a unique db name as IndexedDB is very delicate and we want our test
// to focus on a new DB
var dbName = 'mydb' + '_' + (new Date()).getTime() + '_'
+ Math.round(1000000*Math.random());
var db = null;
var version = 1;
var open = function (version, onSuccess, onUpgradeNeeded) {
var request = null;
if (version) {
request = idb.open(dbName, version);
} else { // 1st time opening?
request = idb.open(dbName);
}
request.onupgradeneeded = function () {
if (onUpgradeNeeded) {
onUpgradeNeeded(request);
}
};
request.onsuccess = function () {
db = request.result;
if (onSuccess) {
onSuccess(request);
}
};
request.onerror = function () {
console.log('error=', request.error);
alert('error=' + JSON.stringify(request.error));
};
};
var createObjectStore = function (name, callback) {
db.close(); // synchronous
version++; // increment version to trigger onupgradeneeded
open(version, callback, function (request) {
request.result.createObjectStore(name, {
keyPath: 'id'
});
});
};
// NOTE: we could create the first store when opening the DB for the first time, but we'll keep
// things simple and reuse our createObjectStore code for both object stores
open(null, function () {
createObjectStore('store1', function () {
createObjectStore('store2', function () {
console.log('done creating both stores');
});
});
});
I tried using a sleep of 2 secs after the DB is closed and reopened and that doesn't appear to work. If there is no workaround then this essentially means that you cannot use the IndexedDB implementation in Safari to dynamically create object stores, which means that you need to know all your object stores before creating a DB.
Unless I am mistaken and someone has a workaround, the best way to dynamically add object stores is to implement a db-per-object-store design. In other words, you should create a new database whenever you need to create a new object store.
Another good option is to use https://github.com/axemclion/IndexedDBShim to emulate IndexedDB with WebSQL.

Retrieving Data From Object Not Working in Ionic

I've attached $cordovaSQLite to my ionic app. Here is a basic example of the code.
function retrieve() {
var q = $q.defer();
var query = 'SELECT user_credentials, user_id FROM Users;';
$ionicPlatform.ready(function (){
$cordovaSQLite.execute(db, query).then(function(res) {
if (res.rows.length > 0) {
console.log("found user");
console.log(res);
console.log(JSON.stringify(res));
q.resolve(res.rows[0]);
} else {
console.log("no rows found");
q.resolve(false);
}
}, function (err) {
q.reject(err);
});
});
return q.promise;
}
Here is the code to open up the db.
if(window.cordova) {
// App syntax
db = $cordovaSQLite.openDB( "CoolApp.db" );
} else {
// Ionic serve syntax
db = window.openDatabase("CoolApp.db", "1.0", "Cool App", -1);
}
When I test my app on Chrome, my logs show this
rows: SQLResultSetRowList
0: Object
user_credentials: "asdf"
user_id: 234
length: 1
rowsAffected: 0
However when I view the logs when running on my iOS app or Safari, I receive
{"rows":{"length":1},"rowsAffected":0,"insertId":1}
My question is why am I not receiving the value of rows? Why does this work on the browser but not on iOS?
You can get the results by querying the rows.item method with the corresponding index if multiple results were returned.
var elements = [];
for (var i = 0; i < result.rows.length; i++) {
elements.push(result.rows.item(i));
}
return elements;
Where result is the object returned by $cordovaSQL when its promise is complete.
Did you try to instantiate a webSQL instead of SQLite DB for your browser?
You can always just go back to SQLite for your device, but modern browsers like Chrome and Firefox don't support SQLite.

Chrome Extension with Database API interface

I want to update a div with a list of anchors that I generate from a local database in chrome. It's pretty simple stuff, but as soon as I try to add the data to the main.js file via a callback everything suddenly becomes undefined. Or the array length is set to 0. ( When it's really 18. )
Initially, I tried to install it into a new array and pass it back that way.
Is there a setting that I need to specify in the chrome manifest.json in order to allow for communication with the database API? I've checked, but all I've been able to find was 'unlimited storage'
The code is as follows:
window.main = {};
window.main.classes = {};
(function(awe){
awe.Data = function(opts){
opts = opts || new Object();
return this.init(opts);
};
awe.Data.prototype = {
init:function(opts){
var self = this;
self.modified = true;
var db = self.db = openDatabase("buddy","1.0","LocalDatabase",200000);
db.transaction(function(tx){
tx.executeSql("CREATE TABLE IF NOT EXISTS listing ( name TEXT UNIQUE, url TEXT UNIQUE)",[],function(tx,rs){
$.each(window.rr,function(index,item){
var i = "INSERT INTO listing (name,url)VALUES('"+item.name+"','"+item.url+"')";
tx.executeSql(i,[],null,null);
});
},function(tx,error){
});
});
self._load()
return this;
},
add:function(item){
var self = this;
self.modified = true;
self.db.transaction(function(tx){
tx.executeSql("INSERT INTO listing (name,url)VALUES(?,?)",[item.name,item.url],function(tx,rs){
//console.log('success',tx,rs)
},function(tx,error){
//console.log('error',error)
})
});
self._load()
},
remove:function(item){
var self = this;
self.modified = true;
self.db.transaction(function(tx){
tx.executeSql("DELETE FROM listing where name='"+item.name+"'",[],function(tx,rs){
//console.log('success',tx,rs)
},function(tx,error){
//console.log('error',tx,error);
});
});
self._load()
},
_load:function(callback){
var self = this;
if(!self.modified)
return;
self.data = new Array();
self.db.transaction(function(tx){
tx.executeSql('SELECT name,url FROM listing',[],function(tx,rs){
console.log(callback)
for(var i = 0; i<rs.rows.length;i++)
{
callback(rs.rows.item(i).name,rs.rows.item(i).url)
// var row = rs.rows.item(i)
// var n = new Object()
// n['name'] = row['name'];
// n['url'] = row['url'];
}
},function(tx,error){
//console.log('error',tx,error)
})
})
self.modified = false
},
all:function(cb){
this._load(cb)
},
toString:function(){
return 'main.Database'
}
}
})(window.main.classes);
And the code to update the list.
this.database.all(function(name,url){
console.log('name','url')
console.log(name,url)
var data = []
$.each(data,function(index,item){
try{
var node = $('<div > '+item.name + '</div>');
self.content.append(node);
node.unbind();
node.bind('click',function(evt){
var t = $(evt.target).attr('href');
chrome.tabs.create({
"url":t
},function(evt){
self._tab_index = evt.index
});
});
}catch(e){
console.log(e)
}
})
});
From looking at your code above, I notice you are executing "self._load()" at the end of each function in your API. The HTML5 SQL Database is asynchronous, you can never guarantee the result. In this case, I would assume the result will always be 0 or random because it will be a race condition.
I have done something similar in my fb-exporter extension, feel free to see how I have done it https://github.com/mohamedmansour/fb-exporter/blob/master/js/database.js
To solve a problem like this, did you check the Web Inspector and see if any errors occurs in the background page. I assume this is all in a background page eh? Try to see if any error occurs, if not, I believe your encountering a race condition. Just move the load within the callback and it should properly call the load.
Regarding your first question with the unlimited storage manifest attribute, you don't need it for this case, that shouldn't be the issue. The limit of web databases is 5MB (last I recall, it might have changed), if your using a lot of data manipulation, then you use that attribute.
Just make sure you can guarantee the this.database.all is running after the database has been initialized.

Categories

Resources