Yii renderPartial with external javascript - javascript

I have a page view that makes an ajax call and updates the contents of the page with renderPartial.
So page.php -> _pagePartial.php (ajax update)
in page.php I want to include the javascript files once, then have the DOM modifications apply after the ajax rendering happens. It doesn't make sense to have this JS file load on every AJAX refresh.
For example in page.php
$baseUrl = Yii::app()->baseUrl;
$basePath = Yii::app()->basePath;
$cs = Yii::app()->getClientScript();
$cs->registerScriptFile($baseUrl . '/js/jquery.ui.js'); // load one time!
then in pagePartial.php
// every ajax partial load
$('#sortable-list-left').sortable({
connectWith:'.productEntryCol',
placeholder: 'ui-state-highlight',
update: function(event, ui) {
var sortOrderLeft = getSortOrder('sortable-list-left');
var sortOrderRight = getSortOrder('sortable-list-right');
var projectId = '" . $project_id . "';
$.ajax({
data: { left: sortOrderLeft, right : sortOrderRight, id : projectId},
url: '/project/ajaxUpdateOrder',
type: 'POST',
success: function(response){
// process JSON response
var obj = jQuery.parseJSON(response);
}
});
}
});
The problem is after _pagePartial loads via AJAX, it can't use the .sortable() method.
What is the proper way to handle this ?
Thanks

The way I handle this is on the main view on the $.load or $.ajax or whatever it is, add your code on the success function.
So for example:
$.get('_pagePartial.php', null, function(html) {
$('#result').html(html);
$('#sortable-list-left').sortable({
//all your sortable code
});
});
Another option is to add your javascript on your ajax loaded page ('_pagePartial.php') into a function like so:
function firejs() {
$('#sortable-list-left').sortable({
//all your sortable code
});
}
Then on your successful ajax call on your main view ('page.php') simply add this:
$.get('_pagePartial.php', null, function(html) {
$('#result').html(html);
firejs();
});
You can bind to an object until it is added to the DOM and it isn't added to the DOM until the ajax call has finished successfully and the result is added to the DOM.
Also just an FYI yii has jqueryui built in you can simply say:
Yii::app()->clientScript->registerCoreScript('jquery.ui');
Yii::app()->clientScript->registerCoreScript('jquery');

For people like me who has the same issue, even with:
Yii::app()->clientscript->scriptMap['jquery.js'] = false;
in the renderPartial and still not work. I've found another solution, way more effective I think. The easiest solution is to set the 4th parameter of renderPartial.
RenderPartial-detail
public string renderPartial(string $view, array $data=NULL, boolean $return=false, boolean $processOutput=false)
It is about processOutput.If you put it to true, then Jquery will be loaded in your render Partial.
Hope this will help someone...

Related

load php page from jquery ajax post unloading the current page

I need to generate a report showing in a php page which will be called by a jquery ajax call. Can any body help me on how to do this.
The jquery ajax post is as following:
$('#report_condition #Submit_rpt_betn_dates').on('click', function(){
var start_dt = $('#report_condition').find('.rpt_betn_dates').find('.start_search_date').val();
var end_dt = $('#report_condition').find('.rpt_betn_dates').find('.end_search_date').val();
alert('you want to generate report between '+start_dt+' and '+end_dt);
$.ajax({
type: "POST",
url: "./report-betn-dates.php",
data: {'startdt':start_dt, 'enddt':end_dt}, //the first parameter in the pair is actually the key for $_POST in PHP
//and it must be withing quotes for ajax to run!!
crossdomain: true,
success: function(response) {
}
});
});
I tried with $('body').html(response); within success parameter of the ajax call. But by this I cannot access the separate css file for the php page. Hence I would like to unload the page containing the ajax call and load the php page with the data sent through $_POST[].
Ajax is for partial content load, asyncronous interactions , etc.. Since what you're trying to achieve is complete new page loaded with its own static resources (css, js) this is the perfect "syncronous" scenario.
So, why wouldn't you use a simpler setup like a form which sends the required vars in post and moves the user to the correct php page?
$('#report_condition #Submit_rpt_betn_dates').on('click', function(){
var fake_form = $('<form method="post" action="report-betn-dates.php">');
var input_start = $('<input type="hidden" name="startdt">');
var input_end = $('<input type="hidden" name="enddt">');
$(fake_form).append(input_start);
$(fake_form).append(input_end):
$(fake_form).submit();
});

Recharge source javascript after loading ajax

This is my website ( work in progress ) -> Link
I use this my code, written on the basis of another creator. -> Link
Ajax Code
$.ajax({
type: 'GET',
url: href,
cache: true,
}).done(function (data) {
......
// Run scripts
$data.filter('script').each(function(){
var scriptTag = document.createElement('script');
scriptTag.text = $(this).html();
document.body.appendChild(scriptTag);
});
});
The code allows you to load the page via ajax, then without refreshing the page. The problem arises when the page has to load javascript, they are not considered and therefore the script in the loaded page does not work.
If I can (if it is not edited) I'll link the site where I'm working and try to click in the first written EdoNetowork, then a link to an account in the topic and you'll see that the code is ignored.
How can I fix?
I think the problem is in updating the javascript page to load. But how can I recharge sources are loaded via javascript src?
You are using $data.filter('script') which is not returning anything, instead use find and in your function you are using $(this).html() but as script has no html inside it so it will not give you anything, instead access attr('src') and append it to your script tag
// your function
$data.filter('script').each(function(){
var scriptTag = document.createElement('script');
scriptTag.text = $(this).html(); // use $(this).attr('src')
// scriptTag.attr('src', $(this).attr('src')) // use it like this
document.body.appendChild(scriptTag);
});
you can also load javascript in your done callback in ajax call usinf jquery getScript()
$.ajax({
.. }).done(function () {
$.getScript( "ajax/test.js", function( data, textStatus, jqxhr ) { ... })
});

jQuery AJAX : How to query an returned HTML document

My question is as follows: I have started using the $.ajax function with jQuery and I am wondering how I work with the return of an HTML page. The request completes and I can console.log the returned HTML page however I would now like to select a single element from that page. I have had several attempts which included:
$(data).find('p');
$('button').click(function() {
$.ajax(funciton() {
dataType: 'html',.
url: 'localhost/sw',
success: function(data) {
// This is where I would like to select a element or node from the complete
// returned html document
});
});
I know i can simply use .load() which you can provide select criteria but .ajax is the root function to begin with and I would like to learn that way as well for more complicated queries. Second half of this would be should I not be trying to select elements this way and just serve up json or a single key phrase instead of the entire html page? All help is appreciated.
Just pass the returned HTML to jQuery, and treat it like a regular jQuery collection:
$.ajax({
dataType: 'html',.
url: 'localhost/sw',
success: function (html) {
var paragraphs = $(html).find('p');
// Manipulate `paragraphs` however you like. For example:
$(document.body).append( paragraphs );
}
});
Joseph's answer above is correct if you just want to get the objects.But if you want to load the content of that element, you may change this:
var paragraphs = $(html).find('p');
to
var paragraphs = $(html).find('p').html();
Hope it helps.

Preventing script execution on ajax load pages with jQuery

I'm trying to load a page using the load() function, the problem is that javascript code on that page is being executed when loading. I use this:
$('#itemid').load('thepage.php #selector', function() {
MY CODE HERE
});
how can i prevent the javascript code from being executed and load only the HTML part that i want?
Use .get() or .post() and process what you get back. Pull the script tags out of your returned code before you append it to the page, or just pull out the code you want:
$.post('thepage.php', {
data: myData
}, function(data) {
var myHTML = $(data).not('script');
$('#itemid').html(myHTML);
});
Or:
$.post('thepage.php', {
data: myData
}, function(data) {
var myHTML = $(data).filter('#selector');
$('#itemid').html(myHTML);
});
Demo: http://jsfiddle.net/jtbowden/wpNBM/
Note: As you mentioned, using a selector with load should accomplish the same thing, as you see in the example. So, if it isn't working this way, something else is going on.
Not sure if I have understood the problem correctly, but you could remove the javascript and just have the html. I assume you want to js bindings to happen on the new page though. So when you load the new page, in the callback, you could call a function that applies the needed bindings.
function applyAfterAjax(){
$(this).find('element').click(function(){alert('clicked');});
}
$('#itemid').load('thepage.php #selector',applyAfterAjax);

How to load a partial view containing JavaScript?

In one of my View pages I have a asp.net mvc PartialView. The PartialView contains some javascript (and jquery). In my asp.net main View I load the PartialView using ajax, within a div tag, in way given below. That is, from controller I return PartialView("_DonorEdit") and in my main page I use javascript to replace the content of the div tag with the PartialView response.
<div class="content" id="content">
#{Html.RenderPartial("_DonorEdit");}
</div>
Everything works fine except the javascript contained in the partialView (_DonorEdit). Thus the question boils down to - How do I have javascript embedded in an div tag and still get it working correctly.
This problem occurs only when the partial view is returned from the ajax call. In the above code, if I directly include the PartialView (on non-ajax request), then the javascript works properly. But if I later replace the content of div using ajax request, the javascript included in PartialView does not work. The embedded javascript simply does not appear along with the Partial View. So there seems to be some other reason, why the javascript embedded in Partial View does not get passed to browser after the ajax request success.
The part of my javascript code
<script type=...>
//Date Picker. This works. I get Calendar popup as expected
$(document).ready(function () {
$("#Donor_BirthDate").datepicker({
dateFormat: "dd-mm-yy",
changeMonth: true,
changeYear: true,
yearRange: "-75:+0"
});
$("#Donor_DateLastDonated").datepicker({
dateFormat: "dd-mm-yy",
changeMonth: true,
changeYear: true,
yearRange: "-20:+1"
});
});
//Dropdown handler. Does not make it in my final View.
function residenceStateChanged(e) {
var url = '#Url.Action("_GetCities", "DropDown")';
var cmbResidenceCityId = $('#ResidenceCityId').data('tDropDownList');
cmbResidenceCityId.loader.showBusy();
$.ajax({
type: 'GET',
url: url,
data: { StateId: e.value, AddSelectOption: true, SelectOption: 'Select' },
traditional: true,
success: function (resp, textStatus, jqXHR) {
cmbResidenceCityId.dataBind(resp);
cmbResidenceCityId.select(0);
cmbResidenceCityId.trigger.change();
},
error: function (jqXHR, textStatus, errorThrown) {
alert(jqXHR.responseText);
},
complete: function () {
cmbResidenceCityId.loader.hideBusy();
}
});
}
....//Some other code omitted. Does not make it in final view.
</script>
I believe your problem is related to this one:
Calling a jQuery function inside html return from an AJAX call
Take a look and see if it helps.
Another way to solve the problem, is to render the partial view in the controller, an return back the html in a json object, as the ajax call result.
In the Controller, you can have a generic method to render a partial view:
private string RenderPartialView(string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
{
viewName = this.ControllerContext.RouteData.GetRequiredString("action");
}
this.ViewData.Model = model;
using (var sw = new StringWriter())
{
ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(this.ControllerContext, viewName);
var viewContext = new ViewContext(this.ControllerContext, viewResult.View, this.ViewData, this.TempData, sw);
viewResult.View.Render(viewContext, sw);
viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
return sw.GetStringBuilder().ToString();
}
}
Then, you will have to add a new action method to your controller that returns the rendered view, i.e.:
public JsonResult GetDonorEdit()
{
return Json(new
{
DonorEditContent = RenderPartialView("_DonorEdit", null)
});
}
In client side, the ajax call can be changed to something like this:
$.ajax({
type: "POST",
url: "GetDonorEdit", // get the correct url of GetDonorEdit action
cache: false
})
.success(function (result) {
$("#content").html(result.DonorEditContent);
})
.error(function (xhr, errStatus, errThrown) {
//...
});
I use this technique, because usually have to return more than one partial view in the same ajax call, and also because it properly execute the javascript code inside the partial views.
Hope it helps.
Call the javascript function in your ajax success part
If you are using this function in multiple pages, why not include it in a script file (maybe named _DonorEdit.js) and including for those pages that use the partial?
You could use something like require.js to make management of this easier.
Alternatively to require.js you can use asset bundling like Cassette.net to manage the dependencies for the pages and any partials you load via ajax.
Then, like in your binding/trigger calls inside of your ajax success handler, you can register whatever events/handlers you need to for the partial.
In the long term something you might want to look at is knockout.js: creating a viewmodel in that _DonorEdit.js file that binds against a template returned in your partial can be extremely powerful and maintainable. If you prefer to still render all the data for the partial serverside, you can still take advantage of knockout's event binding to some degree.

Categories

Resources