jqgrid dataurl completion event - javascript

I am using jQuery to get a list of suppliers for a part number.
I then want to load some extra data about the supplier/part number combination once the edit form appears. The problem is that the dataurl method (which I am calling in the beforeInitData method) to get the suppliers does not complete before the beforeShowForm method executes. Therefore I do not have a supplier to look up when the form first loads. Is there a way to run the function after the dataUrl method completes to get the extra data?
I have tried JQGrid editoptions dataurl not using ajax get? and got it going but I know there will be conflicts because the ajaxSelectOptions method gets called for every request and sometimes my requests will be coming from different places with different requirements.
Here is the code that I am using for my grid:
jQuery("#receiptPartsTable").jqGrid('editGridRow',"new",
{
height:400,
width:800,
reloadAfterSubmit:false,
recreateForm: true,
beforeInitData: function(form)
{
var selectedPart = rowData.part;
var selectedPartQty = rowData.qty;
//Getting list of suppliers
$("#receiptPartsTable").jqGrid('setColProp', 'supplier', { editoptions:{dataUrl:'getSuppliersForPart.php?part=' + rowData.part} });
},
beforeShowForm: function(form)
{
var selectedPart = rowData.part;
var selectedPartQty = rowData.qty;
$('#part').val(selectedPart);
$('#qty').val(selectedPartQty);
//$('#supplier').val() is not set yet;
var supplier = $('#supplier').val();
//This method is getting called before there is a supplier
getPartDetails(rowData.part, supplier);
//Set up onChange listener. After selecting a supplier, get the part details
$('#supplier').change(function() {
var supplier = $('#supplier').val();
getPartDetails(selectedPart, supplier);
});
}

You posted no definition of jqGrid which you use. The context in which you execute the above code is also not quite clear. Do you get rowData before from the currently selected row? Where you define it?
Nevertheless I think that you went in the correct direction and that you found already the correct way to solve the problem. The usage of complete callback of ajaxSelectOptions is probably the only way which you can use. You wrote about some "conflicts", but not posted more details.
I would recommend you to examine properties of this inside of complete callback. jqGrid set context option (see the line) of the $.ajax call (exactly like in the answer which you already found yourself). So you can use this.elem, this.options and this.vl inside of complete callback. this.vl is the value from the cell in case if editing of existing row. Typically it's the name of the option which will be selected. this.options has tree important properties which you can use: this.options.dataUrl, this.options.id, this.options.name. In case of form editing are the values this.options.id and this.options.name the same. In case of inline editing this.options.id will have rowid and _ ad the prefix. It gives you the possibility to execute different code inside of complete callback for different selects where you use dataUrl.
One more remark. In the most cases you can remove call of setColProp from the beforeInitData and use the approach suggested in the answer and the another one:
ajaxSelectOptions: {
data: {
id: function () {
return $("#receiptPartsTable").getGridParam('selrow');
},
part: function () {
return rowData.part;
}
},
complete: function (jqXHR, textStatus) {
var columName = this.options.name, response = jqXHR.responseText;
...
}
}
You can use just editoptions: {dataUrl: "getSuppliersForPart.php"} The URL will be appended with part and id parameters (see the above code). Instead of id you could use getRowData to get content from other columns based of rowid of currently selected row for example.

Related

Pass hidden value in webpage using jqGrid javascript to server code on record insert

I want to insert a new record in the jqGrid with a default field (hidden) as a parameter to the controller. I was able to pass the parameter for the grid get query request by using
datatype: 'json',
postData: {
parameter_to_pass: function () { return document.getElementById('the_hidden_field').value; }
},
but I can't get the create new record to work.
Thanks in advance!
If you use form editing the you can extend the data, which will be send during Add operation, by usage of onclickSubmit callback:
$("#grid").jqGrid("navGrid", "#pager", {},
{}, // edit options
{ // add options
onclickSubmit: function () {
return {
parameter_to_pass: $("#the_hidden_field").val()
};
}
}
);
OK, not much to go on. Can you try breaking it up a bit, see where the problem is coming in? Try setting a variable to the contents of the hidden field and see if you can get the text out of the page for starters. You could also view the source to check that the hidden field is holding the value you think it is.
var hf = document.getElementById('the_hidden_field');
var hfvalue = hf.value;

How to apply the same rules defined in a JS file, containing all rules within document.ready(..) to new posts?

I have a simple JS file that uses Jquery to apply rules to the loaded page.
I starts with the traditional $(document).ready(function(){
Nevertheless, when I load more posts (load more button) or submit a new post, those rules don't apply. I think I understand why...though it is not clear.
Is there a way to apply the same rules to each new added post? Is the only way defining events directly on the html code like e.g onclick....?
I may be a very simple question. I'll appreciate any answers :)
Thanks
JS Code
$(document).ready(function(){
(...)
$('button#cancel').on('click',function () {
$(this).parents('.footer').hide();
$(this).parents('.footer').siblings('.small-textarea-main-feed').removeClass('set-large');
$(this).parents('.footer').siblings('.small-textarea-main-feed').val('');
});
(...)
}); closes all
I am using the following code in load_questions.js to load a new post:
$('form.ajax').submit(function() {
//
var that = $(this),
url = that.attr('action'),
type = that.attr('method'),
data = {};
that.find('[name]').each(function(index, value) {
var that = $(this),
name = that.attr('name'),
value = that.val();
data[name] = value;
});
//event.preventDefault();
$.ajax({
url: url,
type: type,
data: data,
cache: false, // it will force requested pages not to be cached by the browse
success: function(html){
console.log(html);
$("ol#list-feed").prepend(html);
$("ol#list-feed li:first").slideDown(600);
document.getElementById('set-width1').value='';
document.getElementById('tags').value='';
if ($("ol#list-feed > li").size() <= 3) {
$('#loadmorebutton').hide();
} else {
$("ol#list-feed > li:last").remove();
$('#loadmorebutton').show();
}
}
});
//event.preventDefault();
return false;
});
I want that this type of rules apply to new posts I submit.
The DOMDocumentReady event fires exactly once on the page, when the entire HTML document has been loaded and parsed, so any DOM element you should be able to expect be on the page, will be.
Any DOM elements you add to the page from this point on, need to be decorated again. This can be as simple as calling the DOMDocumentReady handler again, in which case you'd want to make it a named function, and pass that named function to $(document).ready(...). Something like this:
var onReadyHandler = function() { };
$(document).ready(onReadyHandler);
$.ajax({
success: function(html) {
$("ol#list-feed").prepend(html);
onReadyHandler();
}
});
Now, it's likely that a better way of handling this (it's really unclear to me what precisely you're trying to accomplish, but that's not a real problem), is to not bind anything to your new posts at all. If you're concerned about events, bind the events to the container you know will be on the page, using 'event delegation' (jQuery link: http://api.jquery.com/delegate/). This pattern takes advantage of the fact that events 'bubble' in the DOM, meaning you can listen higher in the DOM then the elements you actually want to respond to, and just check that the click event happened on the event you do care about ($.delegate does this check automatically). The end result? You bind far fewer event handlers, since you're not decorating each post individually.

how to run an onchange function when page is loaded if the selected box is already selected

Im running into a problem where i have an ajax driven page that is drawn when a user selects something from a simple drop down:
<select id = "selectdepartment">
<option id = "default">Select an option...</option>
....
</select>
and the remainder of the page is drawn using the jquery .change() :
$('#selectdepartment').change(function(){
});
Which then runs some ajax to php script. everything works great, the problem is when i submit a form that was drawn with ajax (using $_SERVER['PHP_SELF'];), the data gets submited, the page reloads, and the page is cleared but the select box is still left where it was. The user has to move to a different option then back to the one the selected originally to re-fire the .change(). that sucks.
I could fix this by passing a php variable in all of my forms, then checking to see the variable set on every page load and if it is draw the page parts then, but this would lead to pretty messy code and it's less than desirable.
There has to be a way to do this with the jquery library, though my knowledge of the javascript language in general is not what i would like it to be. If anyone has any helpful hints please share, dont do it for me though, i wont learn that way :)
edit: code with .trigger
$('#selectdepartment').change(function(){
var department = $('#selectdepartment').val();
var day = $('#data').data('day');
var month = $('#data').data('month');
var year = $('#data').data('year');
//alert (department);
if(department === "Select an option..."){
$('.hiddenuntildepartmentisselected').css({"display":"none"});
}
else{
$('.hiddenuntildepartmentisselected').css({"display":"block"});
}
showpoints(department);
drawpointstable(department, day, month, year);
displaytheuseresforselecteddepartment(department, '');
$('#sendthedepartment').val(''+department+'');
$('#hiddendepartmentidforaddinganewpoint').val(''+department+'');
}).trigger('change');//end run functions
You can use the .trigger() function to immediately trigger the change event handler when the page has loaded:
$('#selectdepartment').change(function() {
// code here
}).trigger('change');
Or if you need to call it elsewhere via JavaScript/jQuery:
$('#selectdepartment').trigger('change'); // or just .change() as a shorthand
Updated
Your button for the form could make use of the onClick attribute, which would invoke a method to parse the form fields and post the data to your php script via .ajax().
In the success event method you then check any flags you need to and modify the element as you desire if needed.
Basic example:
Inside of .ajax():
...
url: 'xxx.xxx.xxx',
async: true,
type: 'POST',
dataType: 'html',
data: JSON.stringify( form_fields ),
beforeSend: function()
{
// Pre send stuff, like starting a loading gif
},
success: function( data, textStatus, xhr )
{
// Be sure you load the page with the content first
$( '#containing-div' ).html( data );
// Do your check here, and modify your element if needed here
if( flagtocheck === 'xxx' )
{
// Modify the element in question...
}
// I call a custom method termed `.ctrls()` here that makes any
// adjustments to the DOM once its loaded/updated.
},
error: function( xhr, textStatus, errorThrown )
{
}
Of course, you'll want to set flagtocheck appropriately in your case.
Hope that helps!
Note regarding edit
This post was edited to be a little more descriptive and more easily understood. Since the person asking the question is already using the .ajax() method, the success event method is the ideal place for doing what the person asking the question is requesting. It is 1 less method invocation to directly modify the element there than using it to call .trigger() or .change() which then also directly modifies the element.

How To Keep a JavaScript Working with ResonseText Data

I've been building an application with PHP/MySQL and JavaScript with Prototype/Scriptaculous.
A page has a search contacts field, with a default set of data in an HTML table. A user types in some characters, and the table get updated.
What's actually happening is the table is getting replaced with a new table and new data.
I've got a JavaScript that works against that table, which is loaded in the standard fashion via script tags at the bottom of the page.
Problem is, it only works on the default data (the part that's loaded with the page), when the search updates the table data, the script stops working. The search still will work since that was originally loaded with the page but it seems my script is unaware of page updates or new data.
How can I get this to work? Do I have to include the script with every Ajax call?
Thanks
Rich
Posting the relevant code would help, but you have most likely attached an event listener to an element that is replaced by the AJAX call.
If that is the case, you will need to recreate and reattach the event handler to the new element, even if that new element is exactly equivalent to the element it is replacing.
OK, I'll post a bit of code here.
But yes an event listener is attached to an element.
Here's a bit of the JavaScript class I was building which looks for events from a search field, collects data from that field and other form elements and sets them up in this.params.
After the data is returned to the AJAX object, it's updated to the page, which is identical to the original code (different rows).
var Compass_Search = Class.create({ ...
search: function() {
$('search_form').observe('change', this.get_data.bind(this));
},
get_data: function(e) {
var ele = e.target;
var filters = $$('.search_option');
if($(ele).tagName == 'INPUT') {
if($(ele).readAttribute('type') == 'checkbox') {
this.watch_filters(filters);
}
}
if(this.default_text == $('search_box').value) {
this.set_text_value('null');
} else {
this.set_text_value($('search_box').value);
}
new Ajax.Request(this.url, {
method: 'post',
parameters: this.params,
onComplete: function(r) {
result_text = r.responseText;
$('main').update(result_text);
}
});
},
...});

Modifying the DOM based on an AJAX result with jQuery

I'm unsure of the best practice for modifying the DOM based on an ajax response. I'll try to let the code do the talking because it's hard to explain.
// page has multiple checkboxes
$("input[type='checkbox']").live('click', function {
var cb = $(this); // for the sake of discussion i need this variable to be in scope
$("form").ajaxSubmit({ dataType: "script" });
}
The server sends a response back, and the js gets eval'd and that means "cb" is out of scope.
What I've done so far is create a couple of helper functions:
var target = undefined;
function setTarget(val) {
target = val;
}
function getTarget() {
return target;
}
And that turns the first snippet of code into this:
// page has multiple checkboxes
$("input[type='checkbox']").live('click', function {
setTarget($(this));
$("form").ajaxSubmit({ dataType: "script" });
}
Then on the server's response I call getTarget where I need to. This seems hackish... Any suggestions?
It's unclear what you're actually trying to do, but I feel like you want to be looking at the success parameter for that AJAX call. The success callback function should execute in parent scope and do what you're looking for.
See 'success' on this page in the jQuery docs.
So what you are trying to do is get the form to submit the content via ajax whenever the user checks/unchecks a checkbox? And because there are several checkboxes, you need to find out which one triggered the submit, so you can change its value to whatever is stored on the server?
If you submit the entire form everytime, why don't you reply with all the checkboxes values, and then change each and every one of them? If not, get the server to reply with the id and the value of the checkbox, then use jquery to find the checkbox with that ID and then change it's value.
How about:
jQuery(function($) {
// give it scope here so that the callback can modify it
var cb,
cbs = $('input[type="checkbox"]');
cbs.live('click', function {
// taking away var uses the most recent scope
cb = $(this);
// disable checkboxes until response comes back so other ones can't be made
cbs.attr('disabled', 'true'); // 'true' (html5) or 'disabled' (xhtml)
// unless you are using 'script' for something else, it's best to use
// a callback instead
$('form').ajaxSubmit({
success : function(response) {
// now you can modify cb here
cb.remove(); // or whatever you want
// and re-enable the checkboxes
cbs.removeAttr('disabled');
}
});
}
});

Categories

Resources