Insert record in mongoDB then update it - Node.Js - javascript

I am new to nodeJS and MongoDB
I want to add a record to the database on the javascript event of PageLoad, then during the visit of the user i add values to this object and then update it in the collection depending on an ID i assigned to this record. I am doing it like the following:
Front-end :
document.addEventListener('DOMContentLoaded', async() => {
var ID = function () {
return '_' + Math.random().toString(36).substr(2, 9);
};
jsLibrary.generateObject().then((objectName) => {
objectName.pageLoadTimeStamp = + new Date();
objectName.identifier = ID;
$.ajax({
type:'POST',
url:'/add',
data:JSON.stringify(objectName),
contentType: "application/json; charset=utf-8",
dataType: "json"
});
});
window.onpagehide = function(){
objectName.PageHideTimeStamp = + new Date();
$.ajax({
type:'POST',
url:'/update',
data:JSON.stringify(objectName),
contentType: "application/json; charset=utf-8",
dataType: "json"
})
};
As you can see i am assigning an ID to an object i'm receiving from a library, then logging the timestamp for pageload and sending it back-end to add it to the database. Then on the event of pageHide I am saving the timestamp of the user leaving the page, and i want to update the record in the collection to re-add it depending on its ID
Back-end: My app.js file
app.post('/add', function(req, res)
{
objName = (req.body);
db.components.insert(objName, function(err,res)
{
if(err){
console.log(err); }
console.log("SUCCESS");
});
});
app.post('/update', function(req, res)
{
objName = (req.body);
db.components.update( { identifier: objName.identifier }, objName, true )
console.log("updated");
});
I get on my console both the values SUCCESS and updated
But when i check the values in my collection; they don't seem to be updated. The pageHideTimeStamp doesn't exist.
The problem is probably with the update, I want to replace the whole record with a new one depending on the ID.
IS there a better practice? Sorry i'm new to this. Thank you
PS: its not practical for me to pass through every parameter i added to this object while updating. There are other parameters I'm adding other than PageHideTimeStamp and there could be more with time

the condition for updating should have only the check you need to apply like it should be ,
let cond = {'id' : '22'} or cond = {'name' : 'sss'} ,
you are using req.body whole object as condition you can try code like this
db.update(condition,data,this.table,function (err,refresh) {
if(err){
//console.log('err controler', refresh)
callback(err, null);
return;
}
//console.log('updated ', refresh)
callback(null,refresh);
});

Use $set for update data
db.components.update( { identifier: objName.identifier }, {$set : objName},function(err,result){
console.log('updated')
})

Related

Change button using CSS or by using scripts

I am using data tables to show data and a button is present opposite to each entry of my data table.
That button has onclick which captures the parameter present in a row and save in array.
I want to change color when certain entry is selected and reset on deselect.
Here is what I am doing,
function select(name){
var property = document.getElementById('checkRule');
if( rArray.includes(name) ){
property.style.backgroundColor = "#FFFFFF"
const index = rArray.indexOf(name);
if (index > -1) {
rArray.splice(index, 1);
}
}else{
rArray.push(name);
property.style.backgroundColor = "#28a0ff"
}
console.log('ARRAY >> ', rArray);
}
This code is only changing color of very first element of of data table.
How shall I make it work?
Assuming that you want to send the ajax request after you select a radio button and you click on go.
You do not need to change the html, but you will have to change the javascript file.
$("#go").click(() => {
var result = $("input:radio[name='doamin']:checked").val();
console.log("result > ", result);
var Data = {
result1: result,
};
console.log("postData > ", Data);
$.ajax({
url: "import",
headers: {
Accept: "text/plain",
"Content-Type": "application/json",
},
type: "POST",
dataType: "html",
data: JSON.stringify(Data),
success: function (data) {
console.log(data);
},
error: function (err) {
console.log(err);
},
});
});
Ideally, you want to send a POST request, as there is a body attached.

Node.js/Express.js Ajax not returning string

I am trying to retrieve passwords in the database via the findOne method. Here is my Ajax:
$.ajax(
{
type: 'GET',
url: '/api/passwords/getPassword',
contentType: 'application/json',
dataType: "string",
async: true,
data: JSON.stringify({
"user_name": "fun.test.net",
"target": "Intern",
"system_type": "Test",
})
}).done(function(data)
{
window.ShowPassword(ele, data);
}).fail(function()
{
console.log("Error - Password Not Found.");
});
}
Along with its supporting function, which just swaps a button out for text (the password):
var buttonId = $(ele).attr('id');
var buttonText = $(this).html();
$('#' + buttonId).replaceWith("<span>" + "hello" + "</span>");
And here is my GET function:
router.get('/getPassword', async (req, res) =>
{
let passwords = await Password.findOne(
{
user_name: req.body.user_name,
target: req.body.target,
system_type: req.body.system_type,
});
if (!passwords) return res.status(404).send('Error 404: The password with the given ID was not found.');
res.send(JSON.stringify(passwords.password));
});
Whenever I call this function, it will throw the error:
TypeError: Cannot read property 'password' of null
at C:\Users\e0186030\Desktop\code\password_service2.0\routes\passwords.js:20:39
Please let me know what's going on! I'm not too familiar with Ajax, so I suspect that's what it is. But the idea is that the get function will return its password. It works in postman, so I know the call works by itself.
Try setting the JSON.stringify() to its own variable then sending it in the res:
const password = JSON.stringify(passwords.password);
res.send(password);
Your res.send() could be sending the password before it is actually stringified. Which would result in a null value. Hope this helps.

how to use ajax in shopping cart session - node js

I want to insert and delete products in my shopping cart without refreshing the page. I'm trying to use ajax in my code but I can't understand what I'm doing wrong. For example, this code should insert something in the data field? Please help me in this question
Below it's my ajax code:
$(function() {
$("#cart_id").click(function(e){
e.preventDefault();
var product;
$.ajax({
type: "GET",
data: product,
url: 'http://localhost:8888/add-to-cart-forward/:id',
success: function(response) {
console.log(response);
}
});
});
});
This it's my node JS code
router.get('/add-to-cart-forward/:id', function (req, res, next) {
var cart = new Cart(req.session.cart ? req.session.cart : {});
Product.findById(productId, function (err, product) {
if (err) throw err;
cart.add(product, product.id);
req.session.cart = cart;
console.log(req.session.cart);
res.render('shop/description', product);
});
});
Alredy done. Its work now. Thanks for attention. I didnt change my node js file, only ajax. This is my ajax code.
$(document).on('click','#cart_id',function(e){
e.preventDefault();
var id = $(this).data('id');
$.ajax({
type: "GET",
data: id,
url: '/add-to-cart-forward/' + id,
success: function() {
console.log(id)
}
});
});
I just changed some fields and separated "id". I wish somebody can use it

Two requests in one time immediatly. ASP MVC + JQuery Ajax

MVC application (ASP.NET MVC, client: jquery).
Problem: The second ajax-request wait, when the first ajax request will done.
I need, when the first and the second ajax-requests executes immediatly in one time.
The page sends to server to determine the count of records (the first ajax-request), very long (~5-7 seconds).
The operator click the buttom to open the card to edit it (the second ajax-request, fast, get the Dto-model).
The user doesn't need to wait the first request, he wants to work immediatly.
As a result, in Chrome in network page, two requests in status 'pending'. The second waits the first.
Question, how can I send requests, to execute asynchronously ?
The first ajax-request:
`window.jQuery`.ajax({
type: 'POST',
url: Url.Action("GetCountBooks", "Book");
contentType: "application/json; charset=utf-8",
dataType: 'json',
data: JSON.stringify({ typeBook: "...", filter: "..." };),
success: function (data) {
// show in UI page the count of books by filter and params
},
error: function (data) {
//show error
}});
public class BookController : Controller
{
[HttpPost]
public NJsonResult GetCountBooks(string typeBook, Filter filter)
{
var data = DbProvider.GetCountBooks(typeBook, filter)
if (data.Result == ResultType.Success)
{
var count = data.Data;
return new NJsonResult
{
Data = new { Data = count }
};
}
return new NJsonResult
{
Data = new { Error = "Error while counting the books." }
};
}
}
The second ajax-request:
`window.jQuery`.ajax({
type: 'POST',
dataType: 'json',
contentType: "application/json",
url: Url.Action("GetBookById", "Book"),
data: JSON.stringify({ id: bookId }),
success: function (data) {
// show jquery dialog form to edit dto-model.
},
error: function (data) {
//show error
}});
public class BookController : Controller
{
[HttpPost]
public NJsonResult GetBookById(int id)
{
var data = DbProvider.GetBookById(id)
if (data.Result == ResultType.Success)
{
var book = data.Data;
return new NJsonResult
{
Data = new { Data = book }
};
return new NJsonResult
{
Data = new { Error = "The book is not found." }
};
}
return new NJsonResult
{
Data = new { Error = "Error while getting the book." }
};
}
}
I Cannot union ajax requests into one! The user can send various second request.
You need a fork-join splitter to fork 2 tasks and join based on some condition.
For example here is my implementation:
function fork(promises) {
return {
join: (callback) => {
let numOfTasks = promises.length;
let forkId = Math.ceil(Math.random() * 1000);
fork_join_map[forkId] = {
expected: numOfTasks,
current: 0
};
promises.forEach((p) => {
p.then((data) => {
fork_join_map[forkId].current++;
if (fork_join_map[forkId].expected === fork_join_map[forkId].current) {
if (callback) callback(data)
}
})
});
}
}}
Pass any number of async tasks (promises) into fork method and join when all are done. The done criteria here is managed by simple global object fork_join_map which tracks the results of your fork-join process (global is not good but its just an example). The particular fork-join is identified by forkId which is 0..1000 in this example which is not quite good again, but I hope you got the idea.
With jQuery you can create promise with $.when( $.ajax(..your ajax call) )
In the end you can join your promises like this
fork([
$.when( $.ajax(..your ajax call 1) ),
$.when( $.ajax(..your ajax call 2) )
]).join(() => {
// do your logic here when both calls are done
});
It's my own implementation, there may be already-written library functions for this in jQuery - I dont know. Hope this will give you a right direction at least.
The solution is to add attribute to Asp Controller: [SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]
http://johnculviner.com/asp-net-concurrent-ajax-requests-and-session-state-blocking/

MVC / AJAX send data to controller and load response in same view

I have a page with three form fields (2 textbox, 1 dropdown), a submit button and a 'refresh' link. I want to be able to click the link and pass two form textbox values to a controller action, and get a list of values to populate the dropdown box. I do not want to submit the form at this stage.
At the moment, I have managed to call the controller action from the link click, but I cannot pass the two form field values in for some reason. Also, the return JSON just takes me to a new page instead of populating my dropdown list. Any pointers would be great as I am new to javascript and MVC. My code is below;
Controller
public ActionResult Find(AddressFormViewModel model)
{
...
var temp = new List<OptionModel>();
temp.Add(new OptionModel {Id = item.Id, Value = item.desc});
return Json(temp, JsonRequestBehavior.AllowGet);
}
HTML
#Html.TextBoxFor(x => Model.HouseNameInput, new { id = "HouseNameInput" })
#Html.TextBoxFor(x => Model.PostCodeInput, new { id = "PostCodeInput" })
#Html.ActionLink("Find","Find", "Address", new { houseInput = Model.HouseNameInput, postcodeInput = Model.PostCodeInput }, new { htmlAttributes = new { #class = "Find" } })
#Html.DropDownListFor(x => Model.AddressOption, Enumerable.Empty<System.Web.Mvc.SelectListItem>(), "-- Loading Values --", new {id = "AddressOptions"})
And lastly, my Javascript method which is retrieving the data from the controller action but not populating the dropdown list (it displays the results in a new page). It is also not successfully sending the form values to the controller action.
$(function () {
$('.Find').click(function (evt) {
$.ajax({
type: 'POST',
url: '#Url.Action("Find","AddressFormSurface")',
cache: false,
async: true,
dataType: "json",
contentType: "application/json; charset=utf-8",
data: {
houseNameInput: $("#HouseNameInput").value,
postCodeInput: $("#PostCodeInput").value
},
success: function (data) {
if (data.exists) {
var ddl = $('#AddressOptions');
ddl.empty();
data.each(function () {
$(document.createElement('option'))
.attr('value', this.Id)
.text(this.Value)
.appendTo(ddl);
});
}
},
error: function (req) {
}
});
// we make sure to cancel the default action of the link
// because we will be sending an AJAX call
return false;
});
});
You have a number of errors in your script which will cause it to fail.
You specify contentType: "application/json; charset=utf-8", but do
not stringify the data (the option should be removed)
You need to use .val() (not .value) to get the values of the
inputs
The data you receiving does not contain a property named exists so
the if block where you append the options will never be hit
In addition it is unnecessary to generate your link using #Html.ActionLink() (your adding route values based on the initial values of the model). Instead just create it manually
Find
and change the script to
var ddl = $('#AddressOptions'); // cache it
$('#find').click(function () { // change selector
$.ajax({
type: 'GET', // its a GET, not a POST
url: '#Url.Action("Find","AddressFormSurface")', // see side note below
cache: false,
async: true,
dataType: "json",
data: {
houseNameInput: $("#HouseNameInput").val(),
postCodeInput: $("#PostCodeInput").val()
},
success: function (data) {
if (!data) {
// oops
return;
}
ddl.empty();
$.each(data, function(index, item) {
$(document.createElement('option'))
.attr('value', item.Id)
.text(item.Value)
.appendTo(ddl);
// or ddl.append($('<option></option>').text(item.Value).val(item.Id));
});
},
error: function (req) {
....
}
}
});
Side note: Also check the name of the controller. Your Html.ActionLink() suggests its AddressController but your script is calling AddressFormSurfaceController

Categories

Resources