How do I force a popup page to post to its controller first before posting to the parent controller? The popup page is setting up some session variables that would be used in the parent page. When the user double click on the grid on the pop-up page, it goes directly to the parent controller instead of going to the child controller.
Here is the parent where the popup is being called
//Javascript to open the popup window
#using (Html.BeginForm("Student", "StudentPage", FormMethod.Get, new { onsubmit = "", id = "student" }))
{
//where the popup window is located
}
Here is the popup form:
#using (Html.BeginForm("Index", "StudentInformation", FormMethod.Post, new {id="StudentSearchForm"}))
{
#(Html
.Telerik()
.Grid((IEnumerable<OverrideStudent>)SessionWrapper.Student.OtherStudentSelected)
.Name("StudentData")
.DataKeys(Keys =>
{
Keys.Add(c => c.StudentID);
})
.DataBinding(databinding => databinding.Server())
.Columns(columns =>
{
columns.Bound(p => p.StudentId)
.Title("Student ID")
.Width(15)
.Sortable(true)
.Filterable(false);
columns.Bound(p => p.StudentDescription)
.Title("Description")
.Width(65)
.Sortable(true)
.Filterable(false);
columns.Command(command =>
{
command.Custom("AddStudent")
.Text("Select")
.DataRouteValues(routes =>
{
routes.Add(o => o.StudentID).RouteKey("StudentID");
routes.Add(o => o.StudentDescription).RouteKey("StudentDescription");
})
.Action("Student", "StudentInfo");
.HtmlAttributes(new { onclick = "PostData(this);StudentSelectClick(this)" });
}).Width(20);
}).ClientEvents(clients => clients
.OnComplete("OnComplete")
//.OnDataBinding("DataBinding")
//.OnDataBound("onRowDataBound")
.OnRowSelected("StudentDoubleClick")
)
.Sortable()
.Selectable()
.Filterable(filtering => filtering
.Enabled(true)
.Footer(true)
.HtmlAttributes(new { style = "padding-right: 0.0em;" }))
}
//This is the script that handles that double click:
function StudentDoubleClick(e) {
var fromCourse = "#SessionWrapper.Student.FromCoursePage";
var fromList = "#SessionWrapper.Student.FromListingPage";
if (fromCourse == "True") {
$('tr', this).live('dblclick', function () {
alert("Inside TR count = " + count);
count = count + 1;
DoSearchStudent(e);
});
}
if (fromList == "True") {
$('tr', this).live('dblclick', function () {
DoSearchStudent(e);
});
}
}
function DoSearchStudent(e) {
var row = e.row;
var StudentID = row.cells[0].innerHTML;
var StudentDescription = row.cells[1].innerHTML;
// alert(procCodeDesc);
var data = { "StudentID": StudentID, "StudentDescription": StudentDescription, "action": "Double Click" };
var url = '#Url.Action("Student", "StudentInfo")';
$.ajax({
url: url,
type: 'post',
dataType: 'text',
cache: false,
async: false,
data: data,
success: function (data) {
window.top.location.href = window.top.location.href;
},
error: function (error) {
alert("An error has occured and the window will not be closed.");
}
});
}
//This is the controller that I need to go to first
public class StudentInfoController : Controller
{
.......
public string Student(string StudentID, string StudentDescription, string action)
{
if (StudentDescription != null)
{
StudentDescription = HttpUtility.HtmlDecode(StudentDescription);
}
try
{
RedirectToAction("AddStudent", "StudentInfo", new { StudentID = StudentID, StudentDescription = StudentDescription, action = action });
}
catch (Exception e)
{
return "Error " + e.ToString();
}
return "Success";
}
}
After the double click, it goes directly to the controller below instead. AS a result, my variables are not being set resulting in null exception.
public class StudentPageController : Controller
{
.......
public string Student(string StudentID, string StudentDescription, Student Students)
{
...........
}
}
It was a timing issue. When the user close the popup window, the popup thread is not done executing. At the same time, another thread starts to run, and not all the session variables are set as of yet. Before closing the popup window, I added a 1 second delay.
setTimeout('StudentWindow.close()', 1000);
Related
I have a button on the parent lwc. When called, it will call a method on the child lwc to perform data update via apex method. Once done, it calls refreshApex to refresh the data on the lightning datatable. RefreshApex will not trigger for some reason.
Now, if I use the child's save button to save the changes, refreshApex will trigger and data will update without any issues.
Appreciate your help!!!
enter image description here
PARENT COMPONENT
</div>
<footer class="slds-modal__footer">
<lightning-button label="Save" variant="brand" onclick={saveModal} class="slds-m-left_x-small"></lightning-button>
<lightning-button label="Cancel" variant="neutral" onclick={closeModal} class="slds-m-left_x-small"></lightning-button>
</footer>
PARENT JS
saveModal() {
//firing a child method
this.template.querySelector("c-reuse-license-key-table").testHandleAction();
}
CHILD COMPONENT
<template if:true={quotelinelist}>
<div class="slds-grid_align-end" style="height: 500px; overflow: auto;">
<lightning-datatable key-field="Id"
data={quotelinelist}
columns={columns}
onsave= {testHandleAction}
oncellchange= {handleRowAction}
draft-values={fldsItemValues}
hide-checkbox-column="true"> <!--suppress-bottom-bar="true"-->
</lightning-datatable>
</div>
</template>
CHILD JS
#wire(getQuoteLinesList,{quoteId: '$parentRecordId', actionType: '$actionTypeForWire'})
cons(result) {
console.log('check result 1 ', result)
this.wiredDataResult = result;
if(result.error) {
console.log('inside wire error')
//this.quotelineList = undefined;
}
else {
console.log('inside else error')
this.quotelinelist = result.data;
}
}
handleRowAction(event) {
lKeyDraftList.push(event.detail.draftValues);
}
#api async testHandleAction() {
let strOriginalKeyValues = JSON.stringify(qlInList);
let strlKeyDraftList = JSON.stringify(lKeyDraftList);
let strDraftValue = [];
lKeyDraftList.forEach(function(c){
console.log('check c', c);
c.forEach(function(c2){
console.log('check c2', c2);
strDraftValue.push(c2);
});
});
await updateQuoteLines({IdToObjectForDraftValues : JSON.stringify(strDraftValue)}) //, IdToObjectForOriginalValues: strOriginalKeyValues
.then(result => {
const toast = new ShowToastEvent({
title: 'Success',
message: 'Records Updated Successfully!!',
variant: 'success'
});
this.dispatchEvent(toast);
this.actionTypeForWire = 'update';
return refreshApex(this.wiredDataResult).then(() => {
console.log('after refresh apex')
this.fldsItemValues = [];
});
})
.catch(error => {
console.log('error');
const toast = new ShowToastEvent({
title: 'Error',
message: 'An Error Occurred!!' + error.message,
variant: 'error'
});
this.dispatchEvent(toast);
}).finally(() => {
console.log('inside final', this.fldsItemValues);
});
}
APEX Controller
#AuraEnabled(cacheable=true)
public static List<SBQQ__QuoteLine__c> getQuoteLinesList(Id quoteId, String actionType) {
List<SBQQ__QuoteLine__c> qLineList = new List<SBQQ__QuoteLine__c>();
if(quoteId != null){
qLineList = [SELECT Id,Name,SBQQ__ProductName__c,SBQQ__Quantity__c,Reused_License_Key__c
FROM SBQQ__QuoteLine__c
WHERE SBQQ__RequiredBy__c != NULL
AND SBQQ__Quote__c = :quoteId
ORDER BY SBQQ__ProductName__c];
}
Boolean callLPUtility = true;
for(SBQQ__QuoteLine__c ql : qLineList) {
if(ql.Reused_License_Key__c != null) {
callLPUtility = false;
break;
}
}
if(callLPUtility == true && actionType == 'begin') {
LicenseProductUtility.toMapLicenseKeyForRenewal(qLineList, getSubscriptionsList(quoteId));
}
return qLineList;
}
#AuraEnabled
public static void updateQuoteLines(String IdToObjectForDraftValues) { //String IdToObjectForOriginalValues
List<Object> items = (List<Object>) JSON.deserializeUntyped(IdToObjectForDraftValues);
List<SBQQ__QuoteLine__c> qlList = new List<SBQQ__QuoteLine__c>();
List<Map<String, Object>> theJsonMapList = new List<Map<String, Object>>();
for(Object itemObj : items) {
theJsonMapList.add((Map<String, Object>) itemObj);
}
for(Object o : theJsonMapList){
SBQQ__QuoteLine__c q = new SBQQ__QuoteLine__c();
q.Id = ((Map<String, Object>) o).get('Id').toString();
q.Reused_License_Key__c = ((Map<String, Object>) o).get('Reused_License_Key__c').toString();
qlList.add(q);
}
Savepoint sp = Database.setSavepoint();
if(!qlList.isEmpty()){
try {
update qlList;
} catch (Exception e) {
Database.rollback(sp);
System.debug('An exception occurred updateQuoteLines: ' + e.getMessage());
}
}
}
I am trying to update an event within my calendar using https://fullcalendar.io/ to show if the current user is registered or not for that event to show that the event color will turn from green to red.
The below methods are within my service method.
public List<TimeTableEvent> GetAllEvents()
{
return db.TimeTableEvents.ToList();
}
public List<EventAttendance> GetAllMembershipEvents(int membershipId)
{
var events = GetAllEvents();
var attendances = db.Attendances.Where(m => m.MembershipId == membershipId);
var membershipEvents = events.Select(e => new EventAttendance
{
Event = e,
Attendance = attendances.FirstOrDefault(a => a.TimeTableEventId == e.Id)
}).ToList();
return membershipEvents;
}
public Attendance AddMembershipToEvent(int membershipId, int eventId)
{
var attendance = new Attendance { MembershipId = membershipId, TimeTableEventId = eventId,
AttendanceStatus = AttendanceStatus.Pending };
db.Attendances.Add(attendance);
db.SaveChanges();
return attendance;
}
I am then using this method within the controller
public JsonResult GetMembershipEvents(int membershipId)
{
var events = service.GetAllMembershipEvents(membershipId);
return Json(events);
}
And then I have a javascript method within my View. That is shown below.
function FetchEventsAndRenderCalendar() {
var userId = 1;//User.Claims.FirstOrDefault(c => c.Type == "Id");
events = []; // clear existing events
$.ajax({
type: "GET",
url: "/Timetable/GetMembershipEvents/" + userId,
success: function (data) {
$.each(data, function (i, json) {
events.push(
{
id: json.event.id,
title: json.event.title,
description: json.event.description,
start: moment(json.event.start),
end: moment(json.event.end),
color: json.isRegistered?"Red":"Green",
allDay: json.event.allDay
}
);
})
I am adding a user to an event so one of the events should be red when it complies. However, it is still showing as green.
Any help would be greatly appreciated.
You can try changing your function from this:
function FetchEventsAndRenderCalendar() {
var userId = 1;//User.Claims.FirstOrDefault(c => c.Type == "Id");
events = []; // clear existing events
$.ajax({
type: "GET",
url: "/Timetable/GetMembershipEvents/" + userId,
success: function (data) {
$.each(data, function (i, json) {
events.push(
{
id: json.event.id,
title: json.event.title,
description: json.event.description,
start: moment(json.event.start),
end: moment(json.event.end),
color: json.isRegistered?"Red":"Green",
allDay: json.event.allDay
}
);
})
to
// Function in which you use await should haveasync delaration
async function FetchEventsAndRenderCalendar() {
var userId = 1;//User.Claims.FirstOrDefault(c => c.Type == "Id");
events = []; // clear existing events
// await means wait for the call to finish and then proceed
const response = await fetch('http://www.example.com/Timetable/GetMembershipEvents/' + userId, {
method: 'GET',
headers: {"Content-Type": "application/json"}// Set required headers. Check Postman call you made.
});
console.log(response);
//Continue doing stuff with response
}
Lot of nodejs projects do this. Try this. If this does not work, try adding async: false in your ajax call.
I have autocomplete control on my grid. After selecting an element from autocomplete I call an event select "onSelectArticle" to import the object using LineBonLivraison_Add action and want to bind it as a json object and not just set values to columns.
The problem happens only to a new added row. For example, when I edit existing rows I can get the properties of the selected object and set values to it like (var item = grid.dataItem(select); item.set("Document", data.Document);) but for new a new row, "item" is null
#section LinesTab {
<style>
.k-widget .templateCell
{
overflow: visible;
}
</style>
<script>
function initMenus(e) {
$(".templateCell").each(function () {
eval($(this).children("script").last().html());
});
}
function onEditGrid(editEvent) {
// Ignore edits of existing rows.
if (!editEvent.model.isNew() && !editEvent.model.dirty) {
//alert("not new dirty")
return;
}
editEvent.container
.find("input[name=Document]") // get the input element for the field
.val("100") // set the value
.change(); // trigger change in order to notify the model binding
}
</script>
<div class="lines-tab-doc">
#(Html.Kendo().Grid<LineBonLivraison>()
.Name("grid-lines-doc")
// Declare grid column
.Columns(columns =>
{
// Cretae all the columns base on Model
columns.Bound(l => l.Article).EditorTemplateName("AutoCompleteArticle");
columns.Bound(l => l.Designation);
columns.Bound(l => l.Quantite);
columns.Bound(l => l.Unite);
columns.Bound(l => l.Commentaire);
columns.Bound(l => l.ReferenceExterne);
columns.Bound(l => l.Commentaire2);
// Edit and Delete button column
columns.Command(command =>
{
command.Edit();
command.Destroy();
}).Width(200);
})
.Events(ev => ev.DataBound("initMenus").Edit("onEditGrid"))
.DataSource(datasoure => datasoure.Ajax()
.Batch(true)
.Model(model =>
{
//model.Id(l => l.Document);
model.Id(l => l.Ligne);
})
.Read(read => read.Action("LinesBonLivraison_Read", "Achat"))
.Create(create => create.Action("LinesBonLivraison_Add", "Achat"))
.Update(update => update.Action("LinesBonLivraison_Update", "Achat"))
.Destroy(delete => delete.Action("LinesBonLivraison_Delete", "Achat"))
.PageSize(10)
)
// Add tool bar with Create button
.ToolBar(toolbar =>
{
toolbar.Create();
toolbar.Save();
})
// Set grid editable.
.Editable(editable => editable.Mode(GridEditMode.InCell).CreateAt(GridInsertRowPosition.Bottom))
.Scrollable(scr => scr.Height(327))
.Sortable()
.Selectable(sel => sel.Mode(GridSelectionMode.Single).Type(GridSelectionType.Row))
.Navigatable()
.Pageable(pageable =>
{
pageable.Refresh(true);
pageable.PageSizes(true);
pageable.Messages(msg => msg.Empty(null));
})
)
</div>
}
AutoComplete Template
<script>
function onSelectArticle(e) {
var dataItem = this.dataItem(e.item.index());
var url = '#Url.Action("LineBonLivraison_Add", "Achat")';
$.ajax({
url: url,
data: {
doc: $("#Numero").val(),
line: e.item.index(),
article: dataItem.Code
}, //parameters go here in object literal form
type: 'GET',
datatype: 'json',
success: function (data) {
if (data == null)
//document.getElementById('labelx').innerHTML = "null";
else {
var grid = $("#grid-lines-doc").data("kendoGrid");
var select = grid.select();
var item = grid.dataItem(select); //prob if it a new row item is null
item.set("Document", data.Document);
item.set("Ligne", data.Ligne);
item.set("Article", data.Article);
//grid.refresh();
}
},
error: function (req, status, error) {
//document.getElementById('labelx').innerHTML = error;
}
});
}
function onAutoComplete() {
return {
text: $("#Article").val()
};
}
<div>
#(Html.Kendo().AutoComplete()
.Name("Article")
.HtmlAttributes(new { style = "width:" + width + ";" })
.DataTextField("Code")
.Filter(FilterType.Contains)
.Enable(enable)
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetArticles", "Fiche").Data("onAutoComplete");
})
.ServerFiltering(true);
})
.Events(e =>
{
e.Select("onSelectArticle");
})
)
Action
public JsonResult LineBonLivraison_Add(int? doc, int? line, string article)
{
Models.Achat.LineBonLivraison l = new Models.Achat.LineBonLivraison()
{
Document = doc,
Article = article,
//Fournisseur = doc.Nom,
Ligne = line,
StyleLigne = "Style1",
ReferenceExterne = article
};
return Json(l, JsonRequestBehavior.AllowGet);
}
I am using a jQuery plugin, jTable. The plugin has the following function to load the table:
$('#PersonTable').jtable('load', { CityId: 2, Name: 'Halil' });
The values in the load function is send as POST data. The plugin also sends two query string parameters (jtStartIndex, jtPageSize) through the URL for paging the table.
An example in the documentation shows a function on how to handle this in ASP.NET MVC but not in Web API Example :
[HttpPost]
public JsonResult StudentListByFiter(string name = "", int cityId = 0, int jtStartIndex = 0, int jtPageSize = 0, string jtSorting = null)
{
try
{
//Get data from database
var studentCount = _repository.StudentRepository.GetStudentCountByFilter(name, cityId);
var students = _repository.StudentRepository.GetStudentsByFilter(name, cityId, jtStartIndex, jtPageSize, jtSorting);
//Return result to jTable
return Json(new { Result = "OK", Records = students, TotalRecordCount = studentCount });
}
catch (Exception ex)
{
return Json(new { Result = "ERROR", Message = ex.Message });
}
}
How my function currently looks: It works fine except that I can't manage to read the POST data (name param):
public dynamic ProductsList(string name = "", int jtStartIndex = 0, int jtPageSize = 0 )
{
try
{
int count = db.Products.Count();
var products = from a in db.Products where a.ProductName.Contains(name) select a;
List<Product> prods = products.OrderBy(x => x.ProductID).ToList();
return (new { Result = "OK", Records = prods, TotalRecordCount = count });
}
catch (Exception ex)
{
return (new { Result = "ERROR", Message = ex.Message });
}
}
My jTable load: (This get called when the user enters text in a input)
$('#ProductTable').jtable('load', {
name: $('#prodFilter').val()
});
I would appreciate any help with how to read both the string parameters in the URL and the POST data in a Web API function.
EDIT:
I used an alternative way to send the data to the API. Instead of sending it in the load function formatted as JSON I used a function for the listAction and sent the data through the URL (See jTable API reference for details):
listAction: function (postData, jtParams) {
return $.Deferred(function ($dfd) {
$.ajax({
url: 'http://localhost:53756/api/Product/ProductsList?jtStartIndex=' + jtParams.jtStartIndex + '&jtPageSize=' + jtParams.jtPageSize + '&name=' + $('#prodFilter').val(),
type: 'POST',
dataType: 'json',
data: postData,
success: function (data) {
$dfd.resolve(data);
},
error: function () {
$dfd.reject();
}
});
});
}
To reload the table based on your filtered results:
$('#ProductTable').jtable('load');
Instead of this:
$('#ProductTable').jtable('load', {
name: $('#prodFilter').val()
});
Try applying the [FromBody] attribute to the name parameter
public dynamic GetProductList([FromBody]string name = "", int jtStartIndex = 0, jtPageSize = 0)
{
...
}
The default binder in Web API will look in the URI for simple types like string, specifying the FromBody attribute will force it to look in the body.
I need to select a value from a Dropdownlist after it has been loaded:
EDIT: In the script associated with the View I have:
//Dropdown cascade call when trigger is called and fill councilDropdown:
$("#districtDropdown").cascade({
url: "/Address/ListCouncilByDistrict",
paramName: "districtId",
firstOption: 'Selecione o Concelho...',
childSelect: $("#councilDropdown")
});
$("#PostalCode").keyup(function () {
loadPTPostalCode();
});
$("#PostalCodeExtension").keyup(function () {
loadPTPostalCode();
});
function loadPTPostalCode()
{
if ($("#PostalCode").val() >= 1000) {
$.ajax({
url: '/Address/GetPTPostalCode',
type: "POST",
dataType: "json",
data: { postalCode: $("#PostalCode").val(), postalCodeExtension: $("#PostalCodeExtension").val() },
success: function (data) {
if (data != null) {
$("#districtDropdown").val(data.PTDistrict_Id); // Set the Dropdown value
$('#districtDropdown').trigger('change'); // Trigger (force the dropdown to load
// *** This is done to soon, the dropdownlist of the Councils is not all loaded yet ***
$("#councilDropdown").val(data.PTCouncil_Id);
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(textStatus)
}
});
}
}
EDIT: The View
#model Heelp.ViewModels.AddressPTViewModel
<h2>Create</h2>
#using (Ajax.BeginForm(MVC.Address.CreateAddressPT(), new AjaxOptions { OnSuccess = "showLoginConfirmationResultMessage" }, new { #id = "AddressForm" }))
{
#Html.AntiForgeryToken()
<div class="address1">
#Html.LabelFor(model => model.Address1)
#Html.TextBoxFor(model => model.Address1)
#Html.ValidationMessageFor(model => model.Address1)
</div>
<div class="address2">
#Html.TextBoxFor(model => model.Address2)
#Html.ValidationMessageFor(model => model.Address2)
</div>
<div class="city">
#Html.LabelFor(model => model.City)
#Html.TextBoxFor(model => model.City)
#Html.ValidationMessageFor(model => model.City)
</div>
<div class="postalCode">
#Html.DisplayNameFor(m => m.PostalCode)
#Html.TextBoxFor(m => m.PostalCode, new { #Value = "" })
#Html.ValidationMessageFor(m => m.PostalCode)
</div>
<div class="postalCodeExtension">
#Html.LabelFor(model => model.PostalCodeExtension)
#Html.TextBoxFor(model => model.PostalCodeExtension)
#Html.ValidationMessageFor(m => m.PostalCodeExtension)
</div>
<div class="postalCodeCity">
#Html.LabelFor(model => model.PostalCodeCity)
#Html.TextBoxFor(model => model.PostalCodeCity)
#Html.ValidationMessageFor(m => m.PostalCodeCity)
</div>
<div id="district">
#Html.DisplayNameFor(m => m.PTDistrict_Id)
#Html.DropDownListFor(m => m.PTDistrict_Id, Model.PTDistrictList, HeelpResources.PTDistrictViewDropDownListFirstRecord, new { id = "districtDropdown" })
#Html.ValidationMessageFor(m => m.PTDistrict_Id)
</div>
<div id="council">
#Html.DisplayNameFor(m => m.PTCouncil_Id)
#Html.DropDownListFor(m => m.PTCouncil_Id, Model.PTCouncilList, HeelpResources.PTCouncilViewDropDownListFirstRecord, new { id = "councilDropdown" })
#Html.ValidationMessageFor(m => m.PTCouncil_Id)
</div>
<p>
<input type="submit" value="Create" />
</p>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
EDIT:
Cascade Function:
// Cascade function
(function ($) {
$.fn.cascade = function (options) {
var defaults = {};
var opts = $.extend(defaults, options);
return this.each(function () {
$(this).change(function () {
var selectedValue = $(this).val();
if (selectedValue == '') {
opts.childSelect.empty();
return;
}
var params = {};
params[opts.paramName] = selectedValue;
$.post(opts.url, params, function (items) {
//$.getJSON(opts.url, params, function (items) {
opts.childSelect.empty();
if (opts.firstOption != "")
opts.childSelect.append(
$('<option/>')
.attr('value', '')
.text(opts.firstOption));
$.each(items, function (index, item) {
// alert(opts.firstOption);
opts.childSelect.append(
$('<option/>')
.attr('value', item.Id)
.text(item.Name)
);
});
});
});
});
};
})(jQuery);
But when I do that, as the Dropdownlist is not still loaded, the val() is not there yet.
For example, if I put an alert message before, it works fine because it as time to load the dropdown.
How can I set the value of the council dropdown only after the dropdown is loaded?
As your requirement "set the value of the council dropdown only after the dropdown is loaded".
You need perform synchronous Ajax request. You can specify the async option to be false to get a synchronous Ajax request.
$.ajax({
url: '/Address/GetPTPostalCode',
type: "POST",
dataType: "json",
data: { postalCode: $("#PostalCode").val(), postalCodeExtension: $("#PostalCodeExtension").val() },
success: function (data) {
if (data != null) {
$("#districtDropdown").val(data.PTDistrict_Id);
$('#districtDropdown').trigger('change');
// *** This is done to soon, the dropdownlist of the Councils is not all loaded yet ***
$("#councilDropdown").val(data.PTCouncil_Id);
}
},
async: false
});
I would update the cascade plugin to trigger an event when the ddl is updated.
(function ($) {
$.fn.cascade = function (options) {
var defaults = {};
var opts = $.extend(defaults, options);
return this.each(function () {
$(this).change(function () {
// #### store reference to changed element for later ####
var self = this,
selectedValue = $(this).val();
if (selectedValue == '') {
opts.childSelect.empty();
return;
}
var params = {};
params[opts.paramName] = selectedValue;
$.post(opts.url, params, function (items) {
//$.getJSON(opts.url, params, function (items) {
opts.childSelect.empty();
if (opts.firstOption != "")
opts.childSelect.append(
$('<option/>')
.attr('value', '')
.text(opts.firstOption));
$.each(items, function (index, item) {
// alert(opts.firstOption);
opts.childSelect.append(
$('<option/>')
.attr('value', item.Id)
.text(item.Name)
);
});
// #### Trigger event ####
self.trigger("update");
});
});
});
};
})(jQuery);
now you can bind to that:
...
// *** #### fixed #### This is done to soon, the dropdownlist of the Councils is not all loaded yet ***
$("#councilDropdown").on("updated",function(){
$(this).val(data.PTCouncil_Id);
});
}
I would say there are two approaches here.
1
The best practice would just be to add a callback functionality to your cascade. It could be done like this:
...
$.post(opts.url, params, function (items) {
//$.getJSON(opts.url, params, function (items) {
opts.childSelect.empty();
if (opts.firstOption != ""){
opts.childSelect.append(
$('<option/>')
.attr('value', '')
.text(opts.firstOption));
$.each(items, function (index, item) {
// alert(opts.firstOption);
opts.childSelect.append(
$('<option/>')
.attr('value', item.Id)
.text(item.Name)
);
});
if( typeof(opts.callback) == "function" )opts.callback();//issue callback
}
});
...
It would be used by setting up cascade here:
$("#districtDropdown").cascade({
url: "/Address/ListCouncilByDistrict",
paramName: "districtId",
firstOption: 'Selecione o Concelho...',
childSelect: $("#councilDropdown"),
callback: function(){ districtCallback(); }
});
and defined in whatever manner you wanted like this:
function districtCallback(){
$("#councilDropdown").val($("#districtDropdown").val());
}
2
Quick and dirty.. jsFiddle demo
success: function (data) {
if (data != null) {
$("#districtDropdown").val(data.PTDistrict_Id); // Set the Dropdown value
$('#districtDropdown').trigger('change'); // Trigger (force the dropdown to load
(function councilVal(){
if( typeof($("#councilDropdown").val()) != "undefined" ){
$("#councilDropdown").val(data.PTCouncil_Id);
}else{
setTimeout(councilVal,50);
}
})()
}
}
Try creating two events on dropdown 1. custom event and 2. change event
When user manually changes then dropdown value then change event will be fired.
$('#dictrctDropdown').change(function (event){
$('#dictrctDropdown').trigger('custom');
});
$('#dictrctDropdown').on('custom', function (event, param1){
// Load council dropdown
if(param1){
$("#councilDropdown").val(param1);
}
});
from "/Address/GetPTPostalCode" success call back raise custom event for "dictrctDropdown"
function loadPTPostalCode()
{
if ($("#PostalCode").val() >= 1000) {
$.ajax({
url: '/Address/GetPTPostalCode',
type: "POST",
dataType: "json",
data: { postalCode: $("#PostalCode").val(), postalCodeExtension: $("#PostalCodeExtension").val() },
success: function (data) {
if (data != null) {
$.getJSON('disctrictURL','data to post (if any)',function(response){
//Load district dropdown
/*
$.each(items, function (index, item) {
// alert(opts.firstOption);
opts.childSelect.append(
$('<option/>')
.attr('value', item.Id)
.text(item.Name)
);
});
*/
$("#districtDropdown").val(data.PTDistrict_Id); // Set the Dropdown value
});
//Now use district id load council dropdown and set value
$.getJSON('councilURL','data to post (if any)',function(response){
//Council dropdown
$("#districtDropdown").val('council id'); // Set the Dropdown value
});
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(textStatus)
}
});
}
Hope this will help !