Calling SQL in JavaScript for loop - javascript

I am writing a set of functions in JavaScript where a user can either add a new trip or edit an existing trip. Each trip can have (0-n) guns associated to that trip. Either way, the save and edit function both call rangeSaveGun. When called from “save new trip” function, this function (below) executes perfectly. The new record is added to the DB and displayed. However, when called from “edit trip” function, the SQL is exactly the same as shown in alert(sql), but the record never saves to the DB. Any idea why? In both scenarios, this is only called to add new guns to the trip (not to edit existing guns).
My question: In the below function, why is the row not being inserted into the DB when this exact same function is called from the “Edit” function instead of the “New” function? Either way the “sql” text is exactly the same (as verified in the “alert”). What am I missing? Both the "new" and the "edit" functions are called via a button click, and simply save or edit the trip and then call this rangeSaveGun function at the end.
I am already using the standard workaround to ensure closure. I can confirm that all 3 variables (tripNum, input2temp, and input3temp) are showing the expected values in all scenarios. All values are numbers.
function rangeSaveGun(tripNum)
{
var tbl2 = document.getElementById("mytable2");
var rowCount=tbl2.rows.length;
for (var i = 1; i < rowCount; i++) {
var el = document.getElementById("GunVal"+i)
if(el != null)
{
(function(i){
var input2temp = document.getElementById("GunVal"+i).value;
var input3temp = document.getElementById("Rounds"+i).value;
var sql = 'INSERT INTO RangeShot (TripID, GunID, Rounds) VALUES ('+tripNum+', '+input2temp+', '+input3temp+')';
db.transaction(function (tx) {tx.executeSql(sql, [])});
alert(sql);
})(i);
}
}
}

I found the problem. It actually was due to me calling an INSERT statement which was still running while another UPDATE statement was running. The DB was locked by the first write statement, and so the second write statement was never executed. I had to re-write my "update" function to call items in different order.
One other thing I ended up changing was to change the buttontype from "submit" to "button".
function rangeUpdateRecord()
{
db.transaction(function (tx) {
var input1temp = document.getElementById("Name").value;
var input2temp = document.getElementById("Address").value;
var input3temp = document.getElementById("Lat").value;
var input4temp = document.getElementById("Lng").value;
var input5temp = document.getElementById("Duration").value;
var input6temp = document.getElementById("Date2").value;
var input7temp = document.getElementById("StartTime").value;
var input8temp = document.getElementById("Notes").value;
var idupdate = $("#id").val();
var tbl2 = document.getElementById("mytable2");
var rowCount=tbl2.rows.length;
for (var i = 1; i < rowCount; i++) {
var el = document.getElementById("GunVal"+i);
if(el != null)
{
(function(i){
var input2temp = document.getElementById("GunVal"+i).value;
var input3temp = document.getElementById("Rounds"+i).value;
var sql = 'INSERT INTO RangeShot (TripID, GunID, Rounds) VALUES ('+idupdate+', '+input2temp+', '+input3temp+');';
db.transaction(function (tx) {tx.executeSql(sql)});
//alert(sql);
})(i);
}
}
db.transaction(function (tx) {
tx.executeSql('UPDATE RangeTrip SET Name = ?, Address = ?, Lat = ?, Lng = ?, Duration = ?, Date2 = ?, StartTime = ?, Notes = ? WHERE id=?', [input1temp, input2temp, input3temp, input4temp, input5temp, input6temp, input7temp, input8temp, Number(idupdate)],rangeLoadAndReset(),onError);
});
});
}

Related

Sequelize transaction stops executing during loop

I am trying to do a transaction that loops through multiple items and inserts them into the database. If i just have 1 item in each array, the code executes fine, it inserts the deployment, the crew and the equipment. However if I have 2 or more items in either equipment or crew, the application just freezes, no error or anything.
The console output looks like this:
Executing (e337b7de-e95f-4d18-a2e9-1216cb8b7d61): START TRANSACTION;
----------------------CREATE DEPLOYMENT---------------
Executing (e337b7de-e95f-4d18-a2e9-1216cb8b7d61): INSERT INTO `deployments` (`id
`,`dateDeployed`,`dateReturned`,`city`,`province`,`country`,`fireName`,`fireNumb
er`,`fireCenter`,`unitNumber`,`comments`,`finalSold`,`status`,`createdAt`,`updat
edAt`,`contractId`,`deploymentTypeId`,`productId`) VALUES (DEFAULT,'2018-03-01',
'Invalid date','1','BC','CAN','1','1','1','1','test','','active','2018-03-08 22:
36:44','2018-03-08 22:36:44','5','1','1');
----------------------CREATE EQUIPEMENT---------------
----------------------CREATE EQUIPEMENT---------------
Executing (default): INSERT INTO `deploymentEquipments` (`createdAt`,`updatedAt`
,`deploymentId`,`equipmentId`) VALUES ('2018-03-08 18:09:31','2018-03-08 22:36:4
4',17,1);
Executing (default): INSERT INTO `deploymentEquipments` (`createdAt`,`updatedAt`
,`deploymentId`,`equipmentId`) VALUES ('2018-03-08 18:09:39','2018-03-08 22:36:4
4',17,2);
My code is like this:
app.post('/deployment', function(req,res,next){
var deployment = req.body;
var crew = req.body.deploymentCrew;
var equipment = req.body.deploymentEquipment;
var deploymentId = "";
//insert new deployment - start transaction, add deployment, get ID, loop through crew, loop through equipment
models.sequelize.transaction(t =>
{
var equipPromises = [];
console.log('----------------------CREATE DEPLOYMENT---------------');
return models.deployment.create(req.body, {transaction: t})
.then(function(newDeployment) {
deploymentId = newDeployment.dataValues.id;
for (var i = 0; i < equipment.length; i++) {
console.log('----------------------CREATE EQUIPEMENT---------------');
var equip = equipment[i];
equip.deploymentId = deploymentId;
equip.equipmentId = equipment[i].id;
var equipPromise = models.deploymentEquipment.create(equip, equipPromises.push(equipPromise));
}
return Promise.all(equipPromises);
})
.then(function() {
console.log('----------------------CREATE STAFF---------------');
var crewPromises = [];
for (var i = 0; i < crew.length; i++) {
var staff = crew[i];
staff.deploymentId = deploymentId;
staff.staffId = crew[i].staff.id;
var crewPromise = models.deploymentCrew.create(staff, crewPromises.push(crewPromise));
}
return Promise.all(crewPromises);
});
}).then(result => {
console.log('deployment added');
res.send(result);
}).catch(err => {
console.log('deployment creation failed');
res.status(401).send({'message':err, 'redirect': '/'});
});
});
Any thought's or ideas why this might be happening would be appreciated.
Thanks
It was actually quite simple, I wasn't adding the transaction into the looped create statements. So now it is like:
//this is the old statement
//var equipPromise = models.deploymentEquipment.create(equip, equipPromises.push(equipPromise));
//this is the new correct way to do it
equipPromises.push(models.deploymentEquipment.create(equip, {transaction:t}));

SharePoint 2013 JSOM User Key From Person Field

Can anyone help me to get the user info from a person column using javascript? So far I have been able to read the list item and return a SP.FieldUserValue from which I can get a numeric Id (not sure what this ID is) and the display name. e.g.
var ManVal = oListItem.get_item("RecruitingManager").get_lookupValue();
var ManId = oListItem.get_item("RecruitingManager").get_lookupId();
How do I take this one step further to create a sp user object?
Ultimately what I'm trying to achieve is to retrieve the details from the list and then populate a people editor.
Ok, I've got it.
Here is my code, hope it helps somebody. I haven't included the method to retrieve the list item, just the line from that function where I'm getting the value of the person.
var _lineManager;
var lineManager = oListItem.get_item("RecruitingManager").get_lookupId();
_lineManager = oWebsite.getUserById(lineManager);
getLineManager();
function getLineManager() {
context.load(_lineManager);
context.executeQueryAsync(onGetUserNameSuccessLM, onGetUserNameFailLM);
}
function onGetUserNameSuccessLM() {
alert(lineManager.get_title());
var schema = {};
schema['PrincipalAccountType'] = 'User,DL,SecGroup,SPGroup';
schema['SearchPrincipalSource'] = 15;
schema['ResolvePrincipalSource'] = 15;
schema['AllowMultipleValues'] = false;
schema['MaximumEntitySuggestions'] = 50;
schema['Width'] = '280px';
var users = new Array(1);
var defaultUser = new Object();
defaultUser.AutoFillDisplayText = lineManager.get_title();
defaultUser.AutoFillKey = lineManager.get_loginName();
defaultUser.Description = lineManager.get_email();
defaultUser.DisplayText = lineManager.get_title();
defaultUser.EntityType = "User";
defaultUser.IsResolved = true;
defaultUser.Key = lineManager.get_loginName();
defaultUser.Resolved = true;
users[0] = defaultUser;
SPClientPeoplePicker_InitStandaloneControlWrapper('peoplePickerDivLinMan', users, schema);
}
function onGetUserNameFailLM(sender, args) {
alert('Failed to get user name. Error:' + args.get_message());
}
The person field (actually called "people picker") has a specific JavaScript function which you might find useful: GetAllUserInfo()
There is a nice article on MSDN:
How to: Use the client-side People Picker control in apps for SharePoint
The relevant code is:
// Get the people picker object from the page.
var peoplePicker = this.SPClientPeoplePicker.SPClientPeoplePickerDict.peoplePickerDiv_TopSpan;
// Get information about all users.
var users = peoplePicker.GetAllUserInfo();
var userInfo = '';
for (var i = 0; i < users.length; i++) {
var user = users[i];
for (var userProperty in user) {
userInfo += userProperty + ': ' + user[userProperty] + '<br>';
}
}
$('#resolvedUsers').html(userInfo);
// Get user keys.
var keys = peoplePicker.GetAllUserKeys();
$('#userKeys').html(keys);
So basically you have to cast your field to a SPClientPeoplePicker and can then use GetAllUserInfo to iterate over all users in the field.

JavaScript: How do I pass a variables in to a JS function, from a for loop?

for (var i=0;i<x.length;i++)
{
var Topic = x[i].getElementsByTagName("text")[0].childNodes[0].nodeValue;
var Content = x[i].getElementsByTagName("description")[0].childNodes[0].nodeValue;
document.write("<li class='withimage'> ");
document.write(Topic);
document.write("<button onclick='show(Topic)'></button>");
document.write("</span><span class='time'>");
var full_time = x[i].getElementsByTagName("created_at")[0].childNodes[0].nodeValue;
var time = full_time.split("+");
document.write(time[0]);
document.write("</span></li>");
}
My function is
function show(head)
{
document.getElementById("content").style.display="none";
document.getElementById("details").style.display="block";
document.getElementById("Heading").innerHTML=head;
}
But in every button click I got the final iterating value in the variable "Topic"
The problem here is that you are not passing the Topic Object for each button. Actually you are passing just the object name. So when you click on any button it 'll search for the variable Topic which in this case 'll be the last Topic object in your iteration.
you try something like this :
for (var i=0;i<x.length;i++)
{
var Topic = x[i].getElementsByTagName("text")[0].childNodes[0].nodeValue;
var Content = x[i].getElementsByTagName("description")[0].childNodes[0].nodeValue;
document.write("<li class='withimage'> ");
document.write(Topic);
document.write("<button onclick='show(" + Topic + ")'></button>");
document.write("</span><span class='time'>");
var full_time = x[i].getElementsByTagName("created_at")[0].childNodes[0].nodeValue;
var time = full_time.split("+");
document.write(time[0]);
document.write("</span></li>");
}

return from JS function

basic JS question, please go easy on me I'm a newb :)
I pass 2 variables to the findRelatedRecords function which queries other related tables and assembles an Array of Objects, called data. Since findRelatedRecords has so many inner functions, I'm having a hard time getting the data Array out of the function.
As it currently is, I call showWin inside findRelatedRecords, but I'd like to change it so that I can get data Array directly out of findRelatedRecords, and not jump to showWin
function findRelatedRecords(features,evtObj){
//first relationship query to find related branches
var selFeat = features
var featObjId = selFeat[0].attributes.OBJECTID_1
var relatedBranch = new esri.tasks.RelationshipQuery();
relatedBranch.outFields = ["*"];
relatedBranch.relationshipId = 1; //fac -to- Branch
relatedBranch.objectIds = [featObjId];
facSel.queryRelatedFeatures(relatedBranch, function(relatedBranches) {
var branchFound = false;
if(relatedBranches.hasOwnProperty(featObjId) == true){
branchFound = true;
var branchSet = relatedBranches[featObjId]
var cmdBranch = dojo.map(branchSet.features, function(feature){
return feature.attributes;
})
}
//regardless of whether a branch is found or not, we have to run the cmdMain relationship query
//the parent is still fac, no advantage of the parent being branch since cmcMain query has to be run regardless
//fac - branch - cmdMain - cmdSub <--sometimes
//fac - cmdMain - cmdSub <-- sometimes
//second relationship query to find related cmdMains
var relatedQuery = new esri.tasks.RelationshipQuery();
relatedQuery.outFields = ["*"];
relatedQuery.relationshipId = 0; //fac -to- cmdMain
relatedQuery.objectIds = [featObjId];
//rather then listen for "OnSelectionComplete" we are using the queryRelatedFeatures callback function
facSel.queryRelatedFeatures(relatedQuery, function(relatedRecords) {
var data = []
//if any cmdMain records were found, relatedRecords object will have a property = to the OBJECTID of the clicked feature
//i.e. if cmdMain records are found, true will be returned; and continue with finding cmdSub records
if(relatedRecords.hasOwnProperty(featObjId) == true){
var fset = relatedRecords[featObjId]
var cmdMain = dojo.map(fset.features, function(feature) {
return feature.attributes;
})
//we need to fill an array with the objectids of the returned cmdMain records
//the length of this list == total number of mainCmd records returned for the clicked facility
objs = []
for (var k in cmdMain){
var o = cmdMain[k];
objs.push(o.OBJECTID)
}
//third relationship query to find records related to cmdMain (cmdSub)
var subQuery = new esri.tasks.RelationshipQuery();
subQuery.outFields = ["*"];
subQuery.relationshipId = 2;
subQuery.objectIds = [objs]
subTbl.queryRelatedFeatures(subQuery, function (subRecords){
//subRecords is an object where each property is the objectid of a cmdMain record
//if a cmdRecord objectid is present in subRecords property, cmdMain has sub records
//we no longer need these objectids, so we'll remove them and put the array into cmdsub
var cmdSub = []
for (id in subRecords){
dojo.forEach(subRecords[id].features, function(rec){
cmdSub.push(rec.attributes)
})
}
var j = cmdSub.length;
var p;
var sub_key;
var obj;
if (branchFound == true){
var p1 = "branch";
obj1 = {};
obj1[p1] = [cmdBranch[0].Branches]
data.push(obj1)
}
for (var i=0, iLen = cmdMain.length; i<iLen; i++) {
p = cmdMain[i].ASGMT_Name
obj = {};
obj[p] = [];
sub_key = cmdMain[i].sub_key;
for (var j=0, jLen=cmdSub.length; j<jLen; j++) {
if (cmdSub[j].sub_key == sub_key) {
obj[p].push(cmdSub[j].Long_Name);
}
}
data.push(obj);
}
showWin(data,evtObj) <---this would go away
})
}
//no returned cmdRecords; cmdData not available
else{
p = "No Data Available"
obj = {}
obj[p] = []
data.push(obj)
}
showWin(data,evtObj) <--this would go away
})
})
}
I'd like to have access to data array simply by calling
function findRelatedRecords(feature,evt){
//code pasted above
}
function newfunct(){
var newData = findRelatedRecords(feature,evt)
console.log(newData)
}
is this possible?
thanks!
Edit
Little more explanation.....
I'm connecting an Object event Listener to a Function like so:
function b (input){
dojo.connect(obj, "onQueryRelatedFeaturesComplete", getData);
obj.queryRelatedFeatures(input);
console.log(arr) //<----this doesn't work
}
function getData(relatedFeatData){
var arr = [];
//populate arr
return arr;
}
So when obj.QueryRelatedFeatures() is complete, getData fires; this part works fine, but how to I access arr from function b ?
Post Edit Update:
Due to the way that this event is being hooked up you can't simple return data from it. Returning will just let Dojo call to the next method that is hooked up to onSelectionComplete.
When init runs it is long before findRelatedRecords will ever be executed/fired by the onSelectionComplete event of the well, which is why you were seeing undefined/null values. The only way to work with this sort of system is to either 1) call off to a method like you're already doing or 2) fire off a custom event/message (technically it's still just calling off to a method).
If you want to make this method easier to work with you should refactor/extract snippets of it to make it a smaller function but contained in many functions. Also, changing it to have only one exit point at the end of the findRelatedRecords method will help. The function defined inside of subTbl.queryRelatedFeatures() would be a great place to start.
Sorry, you're kind of limited by what Dojo gives you in this case.
Pre Edit Answer:
Just return your data out of it. Everywhere where there is a showWin call just use this return.
return {
data: data,
evtObj: evtObj
}
Then your newfunct would look like this.
function newfunct(){
var newData = findRelatedRecords(feature,evt);
console.log(newData);
console.log(newData.data);
console.log(newData.evtObj);
}
If you only need that "data" object, then change your return to just return data;.
Also, start using semicolons to terminate statements.

When I use Web SQL,I am in trouble

I tried to insert some data into web sql database.But I met a problem.
My code :
database();
for(var i=0;i<m.length;i++){
showid = m[i].id;
showtitle = m[i].title;
insert();
}
function database(){
//open the database
db = window.openDatabase("youyanchu", "1.0","youyanchu",500000);
db.transaction(function(tx) {
var table = tx.executeSql("CREATE TABLE showList (id int PRIMARY KEY, title NVARCHAR, finishDate NVARCHAR, status NVARCHAR, tkCount NVARCHAR )");
});
}
//INTEGER NOT NULL PRIMARY KEY
function insert(){
db.transaction(function(ar) {
ar.executeSql("INSERT INTO showList (id, title,finishDate,status) values(?,?,?,?)", [showid,showtitle,'aaa','bbb']);
});
}
m.length is 3 and "m" should be
aaa = {'id':'999','title':'ninini'}
bbb = {'id':'888','title':'ninini'}
ccc = {'id':'777','title':'ninini'}
At last,just "ccc" display in the web sql.
How to insert all data into the database?What mistake I made in the code?
Since tx.executeSql is asynchronous, I believe your loop finishes before the first insert runs.
Hence showid and showtitle will always have the last values of the object m
Try this instead:
for(var i=0;i<m.length;i++){
insert(m[i].id, m[i].title);
}
function insert(id, title){
db.transaction(function(tx) {
txexecuteSql("INSERT INTO showList (id, title,finishDate,status) values(?,?,?,?)", [id, title,'aaa','bbb']);
});
}

Categories

Resources