How to override SAPUI5's Hook Methods - user-interface

I want to call the hook methods onBeforeRendering and onAfterRendering externally. My requirement is, when my 3/4 ajax calls complete that time I am rendering UI parts after that I need to call those two methods.

As said, I think your architecture is wrong. I would have build it something like this:
var self = this;
$.ajax(firstURL, {
method: "GET",
contentType: "application/json",
}).fail(function(response) {
// handle error
}).done(function(data) {
// do something with the returned data from first call
$.ajax(secondURL, {
method: "GET",
contentType: "application/json",
}).fail(function(response) {
// handle error
}).done(function(data) {
// do something with the returned data from second call
$.ajax(thirdURL, {
method: "GET",
contentType: "application/json",
}).fail(function(response) {
// handle error
}).done(function(data) {
// build extra UI elements, for example:
var someContainer = self.getView().byId("myContainer"); // ui element where you add more controls
someContainer.addContent(new com.initrode.MyCustomControl({
value : data.someProperty,
change : self.doSomething
}));
});
});
});
As you see:
No calls to onBeforeRendering/AfterRendering
AJAX calls are nested, yet asynchronous (the Promises solves the "synchronous" issue here)
Set your custom control event handlers (in this case, change) inline, so no extra event registration needed
There is no need to set any control's ID (except for the layout element where you need to add the extra controls needed after your ajax calls have all successfully finished)

As #Qualiture said in the comment, you cannot call those methods as they are hooks, being called by the framework before and after the rendering of a control.
You can however "ask" for a rerendering of the control, which in turn will call both hooks, by calling oControl.rerender() or oControl.invalidate()

I dont know if you can do it for your scenario, but in a similar situation I was able to toggle on the fly rendering (as soon as all the ajax calls needed for a control are completed, the control is rendered) by leveraging model binding in the application.
i.e if a control requires some 'data' object to be loaded, bind the control to a model '/data' that will be updated by your ajax call and manage your control visible attribute with something like {= ${/data}||false }
Actually this is somehow relying on the framework to call the renderer function of the control when it detects a change in the model.

Related

Leaflet onEachFeature not working; related to Ajax call?

I'm fairly new to Javascript and Leaflet, so apologies if I'm missing something obvious here, but...
I'm trying to use Leaflet to overlay a series of lines and points on a map, and I want to open a sidebar whenever the user clicks on one of those lines or points. Since the content of the sidebar will vary depending on which line or point the user clicks, I'm trying to use onEachFeature for the mouse event, since I'll then be able to display information related to the appropriate feature.
The problem, though, is that onEachFeature never seems to be called. Here's my code:
function sortAndVisualizeNetwork(){
$.ajax({
url: "d3/networkdata.json",
async: false,
dataType: "json",
success: function(data){
edges = L.geoJson(data, {
filter: function(feature){
if (includeFeature(feature)){
visualizeFeature(feature);
}
},
onEachFeature: function(feature, layer){
layer.on("click", function(e){
//write stuff to sidebar depending on the feature
sidebar.show();
});
}
})
}
})
}
I've tried replacing the layer.on code with simple alerts, none of which appear, so I know onEachFeature isn't being called. The functions within filter work just fine, though.
I'm wondering if this is related to the fact that this is all nested within a synchronous ajax call?

JQM (jQueryMobile) problem with AJAX content listview('refresh') not working

This is a mock of what I'm doing:
function loadPage(pn) {
$('#'+pn).live('pagecreate',function(event, ui){
$('#'+pn+'-submit').click( function() {
$.mobile.changePage({
url: 'page.php?parm=value',
type: 'post',
data: $('form#'+pn+'_form')
},'slide',false,false);
loadAjaxPages(pn);
});
});
function loadAjaxPages(page) {
// this returns the page I want, all is working
$.ajax({
url: 'page.php?parm=value',
type: 'POST',
error : function (){ document.title='error'; },
success: function (data) {
$('#display_'+page+'_page').html(data); // removed .page(), causing page to transition, but if I use .page() I can see the desired listview
}
});
}
in the ajax call return if I add the .page() (which worked in the past but I had it out side of the page function, changing the logic on how I load pages to save on loading times), make the page transition to the next page but I can see the listview is styled the way I want:
$('#display_'+page+'_page').html(data).page();
Removing .page() fixes the transition error but now the page does not style. I have tried listview('refresh') and even listview('refresh',true) but no luck.
Any thoughts on how I can get the listview to refresh?
Solution:
$.ajax({
url: 'page.php?parm=value',
type: 'POST',
error : function (){ document.title='error'; },
success: function (data) {
$('#display_'+page+'_page').html(data);
$("div#name ul").listview(); // add div wrapper w/ name attr to use the refresh
}
});
Be sure to call .listview on the ul element
If it didn't style earlier, you just call .listview(), bot the refresh function. If your firebug setup is correct, you should have seen an error message telling you that.
I didn't have time to get down to creating some code before you posted your fix, but here's a little recommendation from me:
if(data !== null){ $('#display_'+page+'_page').html(data).find("ul").listview() }
This is a bit nicer than a new global selector. Also - you don't need the div and you can provide a detailed selector if you have multiple ULs.
caution: the above code requires data !== null. If it's null - it will throw an error.
If you add items to a listview, you'll need to call the refresh() method on it to update the styles and create any nested lists that are added. For example:
$('#mylist').listview('refresh');
Note that the refresh() method only affects new nodes appended to a list. This is done for performance reasons. Any list items already enhanced will be ignored by the refresh process. This means that if you change the contents or attributes on an already enhanced list item, these won't be reflected. If you want a list item to be updated, replace it with fresh markup before calling refresh.
more info here.

How do I associate an Ajax error result with the original request?

I am sending data to the server in small bursts using the jQuery ajax function. Each chunk of data is a simple key-value map (the data property passed to the ajax function).
If a request fails, how can my error event handler identify which specific set of data failed to be uploaded?
The function signature of the jQuery error handler is:
error(XMLHttpRequest, textStatus, errorThrown)
Neither textStatus or errorThrown seem useful to identify the failed set of data, and the XHR doesn't seem to offer that capability either.
Simply put, if a request fails, I want to be able to get the id property of the data that I passed to the ajax function. How can I do this?
Check this... From the docs - pay attention to the highlighted section:
The beforeSend, error, dataFilter, success and complete options all take callback functions that are invoked at the appropriate times. The this object for all of them will be the object in the context property passed to $.ajax in the settings; if that was not specified it will be a reference to the Ajax settings themselves.
So, in the error() callback (also success and complete, etc), this will be the object passed to $.ajax() - unless you are using the context parameter to change it.
As a note, the data param passed into $.ajax() will be converted to a serialized string for a GET or POST request
The other option, is to just make sure your error() callback has access to the variable in the same scope:
(function() {
// create a scope for us to store the data:
var data = {id: 1};
$.ajax({
url: '/something-to-genereate-error',
data: data,
error: function() {
console.log(this, data);
}
});
})(); // call the function immediatey
See this fiddle for an example - Note that the data inside of this is "id=1" wereas the data we held a copy of is still {id:1}
Also - Note that the closure here ((function() { .... })()) Is pretty much unnecessary, it is just showing a way to store the data variable before passing it into $.ajax() and the using it in the callback. Most likely this ajax call already lies within a function where you could do this.
Ok, I think I found it (based on my previous answer and the one from gnarf,
$.ajax({
type: "POST",
url: "not-found",
context: {id: 123, name: "hello world"},
error: function(){
console.debug($(this)); //only works in chrome
}
});

Can I make an Ajax request inside an ongoing Ajax request (e.g. on the success callback function)?

I have a jQuery application, a shopping cart, that posts back info to the server, if the text inputfield is changed. This is done in an Ajax request. Now, if the Ajaxrequest is a success, I want to reload the shoppingcart asynchronously. The code is as follows:
$(document).ready(function() {
var jInput = $(":input");
jInput.change(function() {
var vareAntal = $(this).val();
var vareID = $(this).siblings("input#vareID").val();
$.ajax({
type: 'POST',
url: 'checkout.aspx',
data: { 'ID': vareID, 'Antal': vareAntal },
success: function() {
$("#newbasket").load(location.href + " #newbasket>*", "");
}
});
});
});
This works, but only once! If I change the text inputfield, after the page is loaded for the first time, the div with the ID of newbasket reloads asynchronously. But if I try to change it again, nothing happens.
I've tried to do some debugging with Firebug, and the first time I change the text inputfield, it fires a POST-event, and afterwards a GET-event, when the POST-event is succesful. But after that, nothing happens when I change the text inputfield again.
So, how do I achieve triggering the .load() method after each text input change?
I've also tried experimenting with the .ajaxComplete() function, but that, of course, resulted in an infinite loop, since the .load() is an ajax-object.
Instead of .change(func), use .live('change', func) here, like this:
jInput.live('change', function() {
This will make the selector work on any new inputs added as well. When you're replacing the elements like you are currently, their event handlers are lost (or rather, not re-created, because you have new elements). .live() is just for this purpose, it listens for events from old and new elements, regardless of when they were added.

ajax - When to use $.ajax(), $('#myForm').ajaxForm, or $('#myForm').submit

Given so much different options to submit sth to the server, I feel a little confused.
Can someone help me to clear the idea when I should use which and why?
1> $.ajax()
2> $('#myForm').ajaxForm
3> ajaxSubmit
4> $('#myForm').submit
Thank you
I personally prefer creating a function such as submitForm(url,data) that way it can be reused.
Javascript:
function submitForm(t_url,t_data) {
$.ajax({
type: 'POST',
url: t_url,
data: t_data,
success: function(data) {
$('#responseArea').html(data);
}
});
}
HTML:
<form action='javascript: submitForm("whatever.php",$("#whatevervalue").val());' method='POST'> etc etc
edit try this then:
$('#yourForm').submit(function() {
var yourValues = {};
$.each($('#yourForm').serializeArray(), function(i, field) {
yourValues[field.name] = field.value;
});
submitForm('whatever.php',yourvalues);
});
Here is my understanding
$.ajax does the nice ajax way to send data to server without whole page reload and refresh. epically you want to refresh the segment on the page. But it has it's own limitation, it doesn't support file upload. so if you don't have any fileupload, this works OK.
$("#form").submit is the javascript way to submit the form and has same behaviour as the input with "submit" type, but you can do some nice js validation check before you submit, which means you can prevent the submit if client validation failed.
ajaxForm and ajaxSubmit basically are same and does the normal way form submit behaviour with some ajax response. The different between these two has been specified on their website, under FAQ section. I just quote it for some lazy people
What is the difference between ajaxForm and ajaxSubmit?
There are two main differences between these methods:
ajaxSubmit submits the form, ajaxForm does not. When you invoke ajaxSubmit it immediately serializes the form data and sends it to the server. When you invoke ajaxForm it adds the necessary event listeners to the form so that it can detect when the form is submitted by the user. When this occurs ajaxSubmit is called for you.
When using ajaxForm the submitted data will include the name and value of the submitting element (or its click coordinates if the submitting element is an image).
A bit late, but here's my contribution. In my experience, $.ajax is the preferred way to send an AJAX call, including forms, to the server. It has a plethora more options. In order to perform the validation which #vincent mentioned, I add a normal submit button to the form, then bind to $(document).on("submit", "#myForm", .... In that, I prevent the default submit action (e.preventDefault() assuming your event is e), do my validation, and then submit.
A simplified version of this would be as follows:
$(document).on("submit", "#login-form", function(e) {
e.preventDefault(); // don't actually submit
// show applicable progress indicators
$("#login-submit-wrapper").addClass("hide");
$("#login-progress-wrapper").removeClass("hide");
// simple validation of username to avoid extra server calls
if (!new RegExp(/^([A-Za-z0-9._-]){2,64}$/).test($("#login-username").val())) {
// if it is invalid, mark the input and revert submit progress bar
markInputInvalid($("#login-username"), "Invalid Username");
$("#login-submit-wrapper").removeClass("hide");
$("#login-progress-wrapper").addClass("hide");
return false;
}
// additional check could go here
// i like FormData as I can submit files using it. However, a standard {} Object would work
var data = new FormData();
data.append("username", $("#login-username").val());
data.append("password", $("#login-password").val()); // just some examples
data.append("captcha", grecaptcha.getResponse());
$.ajax("handler.php", {
data: data,
processData: false, // prevent weird bugs when submitting files with FormData, optional for normal forms
contentType: false,
method: "POST"
}).done(function(response) {
// do something like redirect, display success, etc
}).fail(function(response) {
var data = JSON.parse(response.responseText); // parse server error
switch (data.error_code) { // do something based on that
case 1:
markInputInvalid($("#login-username"), data.message);
return;
break;
case 2:
markInputInvalid($("#login-password"), data.message);
return;
break;
default:
alert(data.message);
return;
break;
}
}).always(function() { // ALWAYS revert the form to old state, fail or success. .always has the benefit of running, even if .fail throws an error itself (bad JSON parse?)
$("#login-submit-wrapper").removeClass("hide");
$("#login-progress-wrapper").addClass("hide");
});
});

Resources