Knockout Determining dropdownlist selection and update text to database - javascript

I am working on binding some data retreive from database and then update it back to database. The database table is a bit weird in this case but I was given instruction to not modify the existing database.
The thing work as follow:
The database table contain both the GoldMemberCardNo and SilverMemberCardNo, in which only one of them is filled at a time (and another is null).
I am required to determine whether the member is GoldMemberCardHolder or SilverMemberCardHolder based on whether it is null and bind the correct one (both the member category and gold/silver card number) to the dropdownlist and text input on initial page load. The one and only way i am able to differentiate whether the member is gold member or silver member is to see whether the CardNo is filled for the particular member
The admin is then given permission to choose from the selection and enter the card number as they wish, and then submit the form.
Suppose, the user is previously an silver member card holder, and now is required to change to gold member card holder. After the admin fill in the required information, when update, the silver member card will be set to null and gold member card value is updated to database.
I have tried as following but getting stuck here. Since it is computed observable, the ko.observable will always be the same and will not listen to the changes when the value changes. Therefore, the value post is always the initial value. And i think my approach to this solution is pretty much bloated.
function MemberProfile() {
var self = this;
self.SilverMemberCardNo = ko.observable();
self.GoldMemberCardNo = ko.observable();
self.CardNo = ko.observable();
self.MemberCategory = ko.computed(function() {
if(self.SilverMemberCardNo() != null) {
return "0";
else if(self.GoldMemberCardNo() != null) {
return "1";
}
});
self.CardNo = ko.computed(function() {
if(self.SilverMemberCardNo() != null) {
return self.SilverMemberCardNo();
else if(self.GoldMemberCardNo() != null) {
return self.GoldMemberCardNo();
}
});
self.GetMemberProfile() = function() {
$.ajax({
dataType: 'json',
type: 'GET',
url: ...,
success: {
ko.mapping.fromJS(data, {}, self);
}
})
}
self.UpdateMemberProfile() = function() {
if(self.MemberCategory == "0") {
self.SilverMemberCardNo(self.CardNo);
self.GoldMemberCardNo(null)
}
else if (self.MemberCategory == "1") {
self.SilverMemberCardNo(null);
self.GoldMemberCardNo(self.CardNo)
}
$.ajax({
dataType: 'json',
type: 'PUT',
url: ...,
data: {
SilverMemberCardNo: self.SilverMemberCardNo,
GoldMemberCardNo: self.GoldMemberCardNo
......
}
}
}
ko.applyBindings(new MemberProfile());
// Data return from JSON
{
"SilverMemberCardNo": null
"GoldMemberCardNo": "123456789"
....
....
....
}
<select>
<option value="0" text="Silver Member" data-bind="value:MemberCategory"></option>
<option value="1" text="Gold Member" data-bind="value:MemberCategory"></option>
</select>
<input type="text" data-bind="CardNo" />

You could make MemberCategory a simple observable and set it's value using your logic in the function of the self.GetMemberProfile() success event.
function MemberProfile() {
var self = this;
self.CardNo = ko.observable();
self.MemberCategory = ko.observable();
self.GetMemberProfile() = function() {
$.ajax({
dataType: 'json',
type: 'GET',
url: ...,
success: {
ko.mapping.fromJS(data, {}, self);
if (self.SilverMemberCardNo() != null) {
self.MemberCategory("0");
} else if (self.GoldMemberCardNo() != null) {
self.MemberCategory("1");
}
}
})
}
self.UpdateMemberProfile() = function() {
var silverMemberCardNo;
var goldMemberCardNo;
if (self.MemberCategory == "0") {
silverMemberCardNo = self.CardNo();
goldMemberCardNo = null;
} else if (self.MemberCategory == "1") {
silverMemberCardNo = null;
goldMemberCardNo = self.CardNo();
}
$.ajax({
dataType: 'json',
type: 'PUT',
url: ...,
data: {
SilverMemberCardNo: silverMemberCardNo,
GoldMemberCardNo: goldMemberCardNo
}
}
}
Another thing to consider, which you may or may not be able to control, is that this logic would be more secure to execute on the server, instead of the client. Meaning take out all of that logic in javascript and do it on the server. Leaving the client to just present data and send it back.

Related

Cannot POST more than one value with AJAX

I stucked on one thing. I have a 2 grid inside checkboxes. When I selected that checkboxes I want to POST that row data values like array or List. Actually when i send one list item it's posting without error but when i get more than one item it couldn't post values.
Example of my grid
Here my ajax request and how to select row values function
var grid = $("#InvoceGrid").data('kendoGrid');
var sel = $("input:checked", grid.tbody).closest("tr");
var items = [];
$.each(sel, function (idx, row) {
var item = grid.dataItem(row);
items.push(item);
});
var grid1 = $("#DeliveryGrid").data('kendoGrid');
var sel1 = $("input:checked", grid1.tbody).closest("tr");
var items1 = [];
$.each(sel1, function (idx, row) {
var item1 = grid1.dataItem(row);
items1.push(item1);
});
$.ajax({
url: '../HeadOffice/CreateInvoice',
type: 'POST',
data: JSON.stringify({ 'items': items, 'items1': items1, 'refnum': refnum }),
contentType: 'application/json',
traditional: true,
success: function (msg) {
if (msg == "0") {
$("#lblMessageInvoice").text("Invoices have been created.")
var del = $("#InvoiceOKWindow").data("kendoWindow");
del.center().open();
var del1 = $("#InvoiceDetail").data("kendoWindow");
del1.center().close();
$("#grdDlvInv").data('kendoGrid').dataSource.read();
}
else {
$("#lblMessageInvoice").text("Problem occured. Please try again later.")
var del = $("#InvoiceOKWindow").data("kendoWindow");
del.center().open();
return false;
}
}
});
This is my C# part
[HttpPost]
public string CreateInvoice(List<Pm_I_GecisTo_Result> items, List<Pm_I_GecisFrom_Result> items1, string refnum)
{
try
{
if (items != null && items1 != null)
{
//do Something
}
else
{
Log.append("Items not selected", 50);
return "-1";
}
}
catch (Exception ex)
{
Log.append("Exception in Create Invoice action of HeadOfficeController " + ex.ToString(), 50);
return "-1";
}
}
But when i send just one row it works but when i try to send more than one value it post null and create problem
How can i solve this? Do you have any idea?
EDIT
I forgot to say but this way is working on localy but when i update server is not working proper.
$.ajax({
url: '../HeadOffice/CreateInvoice',
type: 'POST',
async: false,
data: { items: items, items1: items1 }
success: function (msg) {
//add codes
},
error: function () {
location.reload();
}
});
try to call controller by this method :)

Reload div fires constantly without event MVC

I am working on a project in Visual studio using MVC. I am trying to reload a div after a btn is clicked and data has been posted to the controller dynamically. I use an Ajax post and return a JSONresult. The code for posting looks like this:
<div id = "DelUser">
#using (Html.BeginForm(null, null, FormMethod.Post, new { id = "Dform" }))
{
<label> Select User(s) to Delete: </label>
#Html.ListBox("Users", ViewBag.Users as MultiSelectList,
new { #class = "chzn-select", #style = "width:250px; height:350 px" })
}
<button class="btn btn-primary dropdown-toggle" id="Button1" type="button" onclick="DeleteUsers()"> Delete Selected </button>
</div>
<script>
function DeleteUsers() {
var myList = []
$("#Users > option:selected").each(function () {
myList.push($(this).val());
});
jQuery.ajax({
type: 'post',
dataType: 'json',
contentType: "application/json; charset=utf-8",
url: 'DeleteU',
data: JSON.stringify(myList),
success: function (data) {
$('#msgbx2').html(data.msg);
//here I am trying to refresh the div after the post but it fires every second
$('#DelUser').html('/Home/DeleteUser');
},
failure: function (errMsg) {
$('#msgbx2').html(data.msg);
}
});
return false;
}
The name of the controller is DeleteUser and the JSONresult controller is DeleteU.
I am trying to do this so that the dropdownlist updates after I delete the selected users. If there is another way to dynamically update this div, any information on that would be good to know too. Thank you in advance.
Here are the Controllers as well:
[HttpGet]
public ActionResult DeleteUser()
{
List<string> u = new List<string>();
object[] users = data.getDataFrmDB("Select username From `users`;");
if (users != null)
{
foreach (object[] user in users)
{
u.Add((string)user[0]);
}
}
ViewBag.Users = new MultiSelectList(u, "Username");
return View();
}
[HttpPost]
public JsonResult DeleteU(List<string> Users)
{
bool good = false;
if (Users != null)
{
foreach (string user in Users)
{
string ins = "DELETE FROM `xcal-server`.`users` WHERE username='"+user+"';";
good = data.insert_update_delete_DB(ins);
List<string> u = new List<string>();
object[] users = data.getDataFrmDB("Select username From `users`;");
if (users != null)
{
foreach (object[] usera in users)
{
u.Add((string)usera[0]);
}
}
ViewBag.Users = new MultiSelectList(u, "Username");
if (good == true)
{
ViewBag.error = "You have successfully deleted user";
}
else
{
ViewBag.error = "There was an issue removing user";
}
}
return Json(new { msg = "You have Successfully deleted Users " });
}
return Json(new { msg = "the passwords entered do not match" });
}
This is just a section of my main page that has other action functions/controllers in it which is why i did not originally post the controllers
You can simply update the existing listbox by removing the currently selected items. Start by removing onclick="DeleteUsers() from the button and use Unobtrusive JavaScript. Since you do not appear to have a POST method for DeleteUser() or a submit button, you may as well also replace #using (Html.BeginForm(...)) with just <form> elements. The script will then be
$('#Button1').click(function () {
var selected = $('#Users option:selected'); // store the selected users
if (selected.length == 0) {
return; // no point making a post
}
var users = [];
$.each(selected, function (index, item) {
users.push($(this).val());
})
$.ajax({
type: 'post',
dataType: 'json',
url: '#Url.Action("DeleteU", "yourControllerName")', // always use Url.Action to generate your url's
data: { users: users },
traditional: true,
success: function () {
// remove the currently selected options
selected.remove();
}
});
})
However a lot of the code in your controller does not make sense. Your adding values to ViewBag and even creating a SelectList but your not returning a view (your returning json), so all that is lost. And even if you were returning a view, your loop keeps overwriting the value of ViewBag.error so that only the last value would be set. Ideally, you should be calling a service to delete the users by passing the user name (or a collection of user names so that they are all deleted in a transaction). But based on you current code, you controller method can be
[HttpPost]
public JsonResult DeleteU(List<string> Users)
{
if (Users == null)
{
// throw an error that can be caught in the ajax error handler
}
List<string> deletedUsers = new List<string>();
foreach (string user in Users)
{
string ins = "DELETE FROM `xcal-server`.`users` WHERE username='"+user+"';";
if (data.insert_update_delete_DB(ins))
{
deletedUsers.Add(user);
}
}
return Json(deletedUsers);
}
and then the ajax success callback
success: function (data) {
$.each(data, function(index, item) {
// remove each item that was successfully deleted in the controller
$('#Users option:contains("' + item + '")').remove();
}
}
i think you need to add a $(document).ready(function(){}); around your script

jQuery argument suddely changes into n.Event object

I have a dropdown on my page,which selected value I take like this:
<select id="campaign" class="form-control">
<option>Choose campaign</option>
<option value="createCampaign">Create new campaign</option>
<?php while($row=$resultForCampaigns->fetch_assoc()){
$campaignName=$row['campaign_name'];
echo "<option value=$campaignName>$campaignName</option>";
}?>
</select>
var campaign = $('#campaign option:selected').val();
But when I'm passing that same campaign value as a argument of new function, and do console.log(campaign) it says:
Here is the whole code:
$(document).ready(function() {
$('#campaign').change(function() {
var campaign = $('#campaign option:selected').val();
console.log(campaign);
if (campaign != 'Choose campaign') {
console.log(campaign);
$('#deleteCampaign').click(function(campaign) {
console.log(campaign);
var r = confirm("Are you absolutely sure you want to delete selected campaign?");
if (r == true) {
var data = {};
data.action2 = "deleteCampaign";
data.campaign = campaign;
$.ajax({
url: "../includes/adapter.php",
type: "POST",
dataType: "JSON",
data: data,
async: true,
success: function() {
if (data) {
console.log(data);
$('#poruka').append('<div class="alert alert-success"><strong>Success!</strong> You have successfully deleted campaign!</div>');
} else {
$('#poruka').append('<div class="alert alert-danger"><strong>Failure!</strong> Something went wrong with deleting your campaign! Please try again</div>');
}
}
});
}
});
}
});
});
So, console.log(campaign) after click on $('#deleteCampaign') turns value of campaign from one that I've gave it, to one that picture represents. Really don't know what's going on, so If anyone could explain me how to get correct value inside function that is tiggered by click, I would be very thankful.
The variable campaign is redefined when you use the same name as a function argument in a lower scope.
Variables are scoped to functions, and function arguments are considered variables, it would be the same as doing
var something = 'stuff';
function go() {
something = 'other stuff';
console.log(something); // obviously "other stuff"
}
The first argument for the click function in jQuery is the event object, you can't pass in anything else.
All you have to do is just remove the argument.
var campaign = $('#campaign option:selected').val();
$('#deleteCampaign').click(function() {
console.log(campaign); // still the value

Comparing user input value with JSON object via ajax to ultimately update page content

On page load for my current project, I have a modal overlay appear that prompts the user to enter a 5 digit long value. From that value, I want to have an AJAX call hit an API to see if that value exists/matches and from there, update the nav bar to say, "Hello, [user]" ([user] being another key value pair from the JSON object that the 5 digit long value is referencing. I'm still new to AJAX, so I'm wondering what the best way to go about doing this. I know the following is completely wrong, but I imagine this is the basic framework for starting out something like this.
$("#inputForm").submit(function(){
$.ajax({
url: "/my/api/url/",
type: "POST",
data: postData
success: function(postData){
//if 5-digit value matches value in the API, update the navbar with name key value pair in the JSON object
}
});
});
Try utilizing change event prompt
$(function() {
var check = function(vals, data) {
if (vals.length === 5 && vals.split("").every(Number)) {
if (vals in data) {
// do `$.ajax()` stuff here
/*
$.ajax({
url: "/my/api/url/",
type: "POST",
data: vals
success: function(returnData) {
var data = JSON.parse(returnData);
// check data and update nav bar
$("#navbar").html("Hi, " + data)
}
error: function() {
evt.preventDefault();
// show error
}
});
*/
$("#navbar").html("Hi, " + data[vals])
}
}
};
var data = {
12345: "abc"
};
var vals = prompt("enter 5 digits");
if (vals !== null) check(vals, data);
$("input").change(function(e) {
check(this.value, data)
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="navbar"></div>
<input type="text" placeholder="enter 12345" />
$("#inputForm").submit(function(evt){
$.ajax({
url: "/my/api/url/",
type: "POST",
data: postData
success: function(returnData){
var data = JSON.parse(returnData);
// check data and update nav bar
}
error: function() {
evt.preventDefault();
// show error
}
});
});

How to save var value outside ajax success function?

I am trying to make some form validation functions. Here is what I have:
<script>
$(document).ready(function() {
var myObj = {};
$('#username').keyup(function () {
id = $(this).attr('id');
validateUsername(id);
});
function validateUsername(id){
var username = $("#"+id).val();
$.ajax({
url : "validate.php",
dataType: 'json',
data: 'action=usr_id&id=' + username,
type: "POST",
success: function(data) {
if (data.ok == true) {
$(myObj).data("username","ok");
} else {
$(myObj).data("username","no");
}
}
});
} // end validateusername function
$('#submit').click(function(){
if (myObj.username == "ok") {
alert("Username OK");
} else {
alert("Username BAD");
}
});
}); // end doc ready
So you can see, when a key is pressed in the textbox, it checks if it's valid. The "data.ok" comes back correctly. The problem is based on the response, I define $(myObj).username. For some reason, I can't get this value to work outside the validateusername function. When clicking the submit button, it has no idea what the value of $(myObj).username is.
I need to use something like this, because with multiple form fields on the page to validate, I can do something like:
if (myObj.username && myObj.password && myObj.email == "ok")
... to check all my form fields before submitting the form.
I know I must just be missing something basic.... any thoughts?
EDIT: SOLVED
All I had to do was change var myObj = {}; to myObj = {}; and it's working like a charm. I think I've been staring at this screen waaaaay too long!
You're not accessing the data that you stored properly. Access the username value this way:
$(myObj).data("username")
Resources:
Take a look at jQuery's .data() docs.
Very simple jsFiddle that shows how to properly set and retrieve data with jQuery's .data() method.
I would store the promise in that global variable and then bind an event to the done event within your submit button click.
$(document).ready(function() {
var myObj = false;
$('#username').keyup(function () {
id = $(this).attr('id');
validateUsername(id);
});
function validateUsername(id){
var username = $("#"+id).val();
myObj = $.ajax({
url : "validate.php",
dataType: 'json',
data: 'action=usr_id&id=' + username,
type: "POST",
success: function(data) {
$('#username').removeClass('valid invalid');
if (data.ok == true) {
$('#username').addClass('valid');
}
else {
$('#username').addClass('invalid');
}
}
});
} // end validateusername function
$('#submit').click(function(){
// if myObj is still equal to false, the username has
// not changed yet, therefore the ajax request hasn't
// been made
if (!myObj) {
alert("Username BAD");
}
// since a deferred object exists, add a callback to done
else {
myObj.done(function(data){
if (data.ok == true) {
alert("Username BAD");
}
else {
alert("Username OK");
}
});
}
});
}); // end doc ready
you may want to add some throttling to the keyup event though to prevent multiple ajax requests from being active at once.

Categories

Resources