Data not binding to Select on first Ajax call - javascript

EDIT:
One unusual thing that i notice is that if i select an option from parent SELECT (which fires AJAX call to bring data for binding the next SELECT ) , if i immediately try to open it it continues to show no options but if I wait for couple of seconds , I am able to see the options !
I am trying AngularJS for first time and facing a problem wherein the SELECT control is not binding on FIRST Ajax call but displays item when AJAX call is done second time. The AJAX is fired on change event of another drop down
var app = angular.module('MyApp', []);
app.controller('MyController', function ($scope, $window) {
$scope.singleSelect = ' ';
$scope.IsVisible = false;
$scope.GetValue = function () {
$scope.IsVisible = true;
$scope.DefaultLabel = "Loading.....";
$.ajax({
type: "POST",
url: "../ContentPages/frmManualAccess.aspx/BindDelegationLevel",
data: "{pDelegationLevel :'ALL'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
console.log(JSON.parse(msg.d));
/* Gives array of 3 objects
[{"DelegationCode":"Customer","DelegationName":"Customer"},
{"DelegationCode":"Segment","DelegationName":"Segment"},
{"DelegationCode":"SBUM","DelegationName":"Customer"}]
*/
$scope.myOptions = JSON.parse(msg.d);
$scope.defaultDelegationLevel = $scope.myOptions[0].DelegationCode;
},
error: function (xhr, errorType, exception) {
var varResponseText = jQuery.parseJSON(xhr.responseText);
alert(varResponseText.Message);
}
});
}
});
And in HTML the SELECT i am trying to bind is below
<select ng-model="defaultDelegationLevel"
ng-options="option.DelegationName as option.DelegationCode for option in myOptions" >
</select>
I dont know why its happening , please help in this issue. Also an empty option appears as first option that i am trying to remove.

Related

how to execute a specific code after a ajax

I have a function in which uses ajax which populate a select element of options from my database, here is the code of the function.
function Filtering_GetRole(roleElement) {
$.ajax({
type: "POST",
url: "IROA_StoredProcedures.asmx/Filtering_GetRole",
data: "",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
var roletooldetails = response.d;
var appendItem = "";
$(roleElement).empty();
$.each(roletooldetails, function (index, Filtering_GetRoleInfo) {
var activeappend = "";
var id = Filtering_GetRoleInfo.id;
var role = Filtering_GetRoleInfo.Role;
activeappend = "<option value=" + id + ">" + role + "</option>";
appendItem += activeappend;
});
$(roleElement).prepend('<option disabled="disabled" selected="selected" value="">Select Tool</option>')
$(roleElement).append(appendItem);
},
error: function (XMLHttpRequest) {
console.log(XMLHttpRequest);
alert("error in Filtering_GetTool");
}
});
}
which I call like this
var slcRole = $(this).closest(".td-span-buttons").closest(".tr-span-buttons").find(".slc-role"); var holdRoleId = slcRole.val();
Filtering_GetRole(slcRole);
slcRole.val(holdRoleId);
but the problem is since I use ajax the code slcRole.val(holdRoleId); will execute first resulting to the value not selected on the option element. How can I do that when the ajax code finished this code will execute. Sorry for the bad english
The another way to make sure your ajax request has been processed is to use jQuery.when(), but the best way is to put slcRole.val(holdRoleId) into success callback.
Just put slcRole.val(holdRoleId); into success.
Else, js will execute without waiting ajax done.
I think you need to execute this after success or error so instead putting in any callback or after your Filtering_GetRole put it in the complete callback of ajax have a look here. It will execute code within complete block when ajax is complete. Hope this will help.
You can use complete function. complete executes only after the "success" of ajax. Following code will be helpful to you.
success: function (response) {
// Your code
},
complete: function (response) {
slcRole.val(holdRoleId);
},
error: function (XMLHttpRequest) {
// Your code
}

Why does the dropdown displays options one by one on first click when using append()

$(document).on('focus', '.resource_person', function() {
var topic_code = $(this).attr('id');
var rp_reference = $(this).attr('selected-rp');
var option = '';
$.ajax({
type: 'POST',
url: siteUrl + 'course_management/Training_courses/topic_rp',
data: {topic_code: topic_code},
dataType: 'json',
success: function(source) {
$('.resource_person[id="'+topic_code+'"]').empty();
for (var key in source) {
if (source[key] != rp_reference) {
option += '<option value="'+source[key]+'">'+key+'</option>';
} else {
option += '<option value="'+source[key]+'" selected="">'+key+'</option>';
}
}
console.log(option);
$('.resource_person[id="'+topic_code+'"]').append(option);
}
});
});
This what was happening when I first click the dropdown
After clicking it for the second time it goes back to the normal behavior of dropdown
On first click it makes request causing delay to show items, but it uses cahce on second request.
If you force request not to use cache, same delay will happen every time:
$.ajax({
cache: false,
//other options...
});
Note: Setting cache to false will only work correctly with HEAD and
GET requests.

Send Chosen Selected Values Array to Controller - MVC

So, I have a view with a chosen search box, a button "Add" (btn-default) and a button "Edit" (breadcrumb) . When I click the Add button, the ajax sent me a table with the values (in this case, funcionaries) selected in the chosen text box.
I want that, when I click on the Edit button, send the chosen values (can be one, or hundreds of values) to another controller to return another view.
Don't want to use ajax because I want to use a new view on totally.
On the controller side, when I send the data with javascript, I always get null. Why?
View
<script>
$(document).ready(function () {
$(".btn-default").on("click", function (event, params) {
$.ajax({
url: '#Url.Action("EditarPonderacoesEspecial", "Sorteios")',
type: 'POST',
dataType: 'html',
cache: false,
traditional: true,
data: { bdoIds: $(".chosen-select").val() },
success: function (responseText, textStatus, XMLHttpRequest) {
$("#MyDiv").empty();
$("#MyDiv").html(responseText);
},
error: function () { }
})
});
$(".breadcrumb").on("click",function (event, params) {
bdoIds = $(".chosen-select").val();
$.post("/Sorteios/EditarPonderacoesEspecialSecond/", bdoIds);
});
});
Controller
public ActionResult EditarPonderacoesEspecialSecond(string[] bdoIds)
{
//do whatever I want with the bdoIds
return View();
}
I had tried many different ways, but the controller always receive the parameter as null. What I am doing wrong? Thanks!
Your controller action is expecting an array of strings.
Assuming .chosen-select is a select list as that part is missing from the question.
First read the selected values into an object as follows:
var selectedValues = [];
$(".chosen-select :selected").each(function() {
selectedValues.push($(this).attr('value'));
});
Then send them as follows:
$(".breadcrumb").on("click",function (event, params) {
var selectedValues = [];
$(".chosen-select :selected").each(function() {
selectedValues.push($(this).attr('value'));
});
$.post("/Sorteios/EditarPonderacoesEspecialSecond/", { bdoIds: selectedValues });
});
Declare Global array like
var SelectedArray = new Array();
When you select multiple selectlist item each time push value in SelectedArray
$('#ChosenId').chosen().change(function () {
SelectedArray = $('#ChosenId').chosen().val();
});
Then your ajax data is like
data: { bdoIds: SelectedArray },

DOM timing or wrong code?

I've got two multi select list boxes, the first one allows someone to select a team.
The second one shows the members related to the team. When the first list box (the team) is selected I make an ajax call to fill the members of that team. I'm also using the chosen library. This is all working fine however, I needed a way to remove the x from the listbox selected value so that users don't think they can remove a member from the team.
$("#MainContent_lbMembers_chosen a").removeClass("search-choice-close");
The above code works when I throw that in a console window, but if I have it in my if condition it doesnt seem to work:
$("#MainContent_lbTeams").on('change', function() {
//was a value selected?
var latest_value = $("option:selected:last", this).val();
var latest_text = $("option:selected:last", this).text();
if ($("#MainContent_lbTeams :selected").length > 0) {
$("#dTeamNotice").show();
$("#MainContent_lblTeamMembers").text("Members of '" + latest_text + "':");
PopulateMembers(latest_value);
$("#MainContent_lbMembers_chosen a").removeClass("search-choice-close");
$("#trMembers").fadeIn();
} else {
//hide it...
$("#dTeamNotice").css("display", "none");
$("#trMembers").hide();
}
});
Basically the change event grabs the most recently selected text and value. If the length of what is selected > 0 I load the members of my team with PopulateMembers:
function PopulateMembers(buCompanyTeamID) {
$('#<%=lbMembers.ClientID %>').empty().append('<option selected="selected" value="0">Loading...</option>');
$("#<%=lbMembers.ClientID %>").trigger("chosen:updated");
$.ajax({
type: "POST",
url: "/Code/WebServices/Utilities.asmx/GetTeamMembers",
data: '{buCompanyTeamID: ' + buCompanyTeamID + '}',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: OnMembersPopulated,
failure: function (response) {
alert(response.d);
}
});
}
function OnMembersPopulated(response) {
PopulateControl(response.d, $("#<%=lbMembers.ClientID %>"), true);
}
function PopulateControl(list, control, selected) {
if (list.length > 0) {
control.removeAttr("disabled");
control.empty().append('<option selected="selected" value="0"></option>');
$.each(list, function () {
if(selected)
control.append($("<option selected></option>").val(this['Value']).html(this['Text']));
else
control.append($("<option></option>").val(this['Value']).html(this['Text']));
});
}
else {
control.empty().append('<option selected="selected" value="0"><option>');
}
control.trigger("chosen:updated");
}
But I cannot understand why in a console window I can do this:
$("#MainContent_lbMembers_chosen a").removeClass("search-choice-close");
And it removes the x from the chosen selected value so that a user cannot remove an item, but within the if condition this doesnt have any effect.
I even tried disabling like so:
$("#MainContent_lbMembers").attr('disabled', true).trigger("chosen:updated");
This only works in a console as well, is it some timing issue or something else?
PopulateMembers() contains an asynchronous Ajax call. So, if you are expecting:
PopulateMembers(latest_value);
$("#MainContent_lbMembers_chosen a").removeClass("search-choice-close");
to operate on the results of the ajax call in PopulateMembers(), then you do indeed have a timing problem. The Ajax call will complete some time in the future, long after PopulateMembers() has finished and long after you've executed the .removeClass() statement.
To operate on the results of PopulateMembers(), you have to either put your code in the success handler of that ajax call or restructure your code so that PopulateMembers() will call a callback when it's done and you can do the .removeClass() in that callback.
I would suggest using promises like this:
// return the ajax promise from PopulateMembers
function PopulateMembers(buCompanyTeamID) {
$('#<%=lbMembers.ClientID %>').empty().append('<option selected="selected" value="0">Loading...</option>');
$("#<%=lbMembers.ClientID %>").trigger("chosen:updated");
return $.ajax({
type: "POST",
url: "/Code/WebServices/Utilities.asmx/GetTeamMembers",
data: '{buCompanyTeamID: ' + buCompanyTeamID + '}',
contentType: "application/json; charset=utf-8",
dataType: "json"
}).then(onMembersPopulated, function (response) {
alert(response.d);
});
}
$("#MainContent_lbTeams").on('change', function() {
//was a value selected?
var latest_value = $("option:selected:last", this).val();
var latest_text = $("option:selected:last", this).text();
if ($("#MainContent_lbTeams :selected").length > 0) {
$("#dTeamNotice").show();
$("#MainContent_lblTeamMembers").text("Members of '" + latest_text + "':");
// act only when the returned promise is resolved
PopulateMembers(latest_value).then(function() {
$("#MainContent_lbMembers_chosen a").removeClass("search-choice-close");
$("#trMembers").fadeIn();
});
} else {
//hide it...
$("#dTeamNotice").css("display", "none");
$("#trMembers").hide();
}
});

You cannot apply bindings multiple times to the same element

I have a Bootstrap modal, and every time it shows up I will use KO to bind a <select> dropdown.
HTML:
<select id="album" name="album" class="form-control" data-bind="options: availableAlbums">
</select>
JavaScript:
$('#uploadModal').on('show.bs.modal', (function () {
function AlbumsListViewModel() {
var self = this;
self.availableAlbums = ko.observableArray([]);
$.ajax({
url: "../../api/eventapi/getalbums",
type: "get",
contentType: "application/json",
async: false,
success: function (data) {
var array = [];
$.each(data, function (index, value) {
array.push(value.Title);
});
self.availableAlbums(array);
}
});
}
ko.applyBindings(new AlbumsListViewModel());
}));
However, on the second showing, KO will present me with this error:
Error: You cannot apply bindings multiple times to the same element.
The error message says most of it. You have two options:
Call the applyBindings function once, when your page loads. KO will automatically update the View when you update the model in a AJAX success function.
Call the applyBIndings function on each AJAX success, but supply additional parameters to tell it what element to bind to.
Most likely the first option is what you're looking for. Remove the call from the $('#uploadModal').on call and place it on document load (if you haven't already).
To see what I mean, here's two fiddles:
Your current code with the error you mention.
Refactored version that doesn't have the error.
The latter tries to stay as close as possible to your initial version (so as to focus on the problem at hand), and goes along these lines:
function AlbumsListViewModel() {
var self = this;
self.availableAlbums = ko.observableArray([]);
}
var mainViewModel = new AlbumsListViewModel();
ko.applyBindings(mainViewModel);
$('#uploadModal').on('show.bs.modal', (function () {
// Commenting things out to mock the ajax request (synchronously)
var data = [{Title:'test'}];
/*$.ajax({
url: "../../api/eventapi/getalbums",
type: "get",
contentType: "application/json",
async: false,
success: function (data) {*/
mainViewModel.availableAlbums.removeAll();
var array = [];
$.each(data, function (index, value) {
array.push(value.Title);
});
mainViewModel.availableAlbums(array);
/*}
});*/
}));

Categories