Yii 2.0 & Ajax/renderPartial conflict

[size=2]Hi Yii developers,

Just wondering what the story is for Yii 2.0 and the Ajax & renderPartial conflict. Is this going to be addressed in the next major release? Is it even addressable? I think it throws many people for a loop and it’s one example that contributes to Yii’s perceived steep(ish) learning curve.

Maybe this would be a good place to start a brain storm for solutions. Any ideas?

Cheers,

Matt[/size]

I think Yii 2 must resolve the issue of multiple delete confirm, pagination multiple requests etc.

if and only if loaded via ajax and multiple times!!!

This is a very frequent problem discussed on the forum…

The problem arrise because some JS files (but even JS code snippets) are re-included with the ajax call… in the first place jquery.js… but even other JS files…

Main problem is - how can YII know what files has been already included from the previous call?

One solution would be to keep included files in sessions and every time a JS file (and snippet) needs to be included to check the session for the name of the file (or snippet)… I’m not sure on how would that affect the performance as memory consumption and as checking every JS file that is included…

The other solution that one forum user made is to have a jQuery ajax event handler and to check script names when they are included… and to deny those that already are… problem with this solution is that while the files will not be included they are still downloaded to the client… and works only for files not for Yii/JS snippets

All this is not a problem if you "understand" how ajax calls works and what they do (need to do)… as the solution is by including all needed JS files and snipets in the main view… and on renderpartials to only return clean HTML or json…

Sometime this is not possible, for example when using CGridView in the renderPartial… in those cases again all the JS files needs to be included by the main view file and then scriptMap can be used to prevent loading of those files on ajax calls…

I’m open for some “creative” ideas on how to solve this.

My solution to this was to keep a js array of loaded assets in the browser.

It’s a little bit messy that this list then needs to be sent with every ajax request (only ones that would actually return html) which then get used with the script map to filter them out.

This allows the first call to include the scripts and run them and all subsequent calls ignore the loaded scripts.

One issue I did have with this though is files with the same name will ignored so doesn’t help where some widgets have the same name for css files.

the main problem is wrong die live usage…

My solution (and I rewrote my yii .js scripts…) is to attach to body attribute…

so instead of attach event again and again for example, they attached only if body not have some tag…

I used to use the solution you said, all js/css files in the first request, then a couple months ago I adapted it to a more complex solution.

Yii2 should have a response object. It should also contain a js script to handle ajax responses.

Ajax requests send the response in json, sending the list of js/css files and scripts/styles ( registered in clientScript ) to be include and executed, along with the response body , something like this:


{

 content:'some html or json here',

 scriptFiles:['list of js files']

 cssFiles:['list of css files'],

 styles:{

   styleID:'some css style here'

 },

 scripts:{

  scriptID:'some javascript',

  otherScript:'other javascript to be executed'

 }

}

The js object that handles ajax requests is a singleton that will contain all js/css files and styles/scripts already executed.

It will then include the new js and css files, after that it will execute the styles and scripts.

clientScript should be modified to work with the response class.

Then in my js file what I do is to check the response type, if json it will be handled by the response object.

The BIG question I’ve never seen to answer before is…TACHANNN: How does it get solved by other Frameworks like Kohana, Codeigniter, Zend, RoR, Web2py, Django, etc. etc.? Or is it a common and history problem on ServerSide Frameworks?

If the way goes through the first question, the answer to this problem is: JUST COPY THAT, by the other hand, if the way goes thought the second question, the answer is: THERE IS NO RIGHT SOLUTION to this problem, because it didn’t get solved by dozens of historical and well known frameworks in the past.

I hope I could help on this big issue Im suffering ourselfs in our platform :smiley:

regards,

alex

P.S: In my opinion this question (problem) should never answer (resolved) in Yii 2.0 only, because this is a big issue to solve for yii 1.1.x users also, to not force us to upgrade a major version (with the stability and backward compatibility issues it could involve for productions enviroments).

Silly, I know, but I’ve resorted to suppressing widgets and extensions registering scripts, choosing to see what’s needed and including it all in one file - at the bottom of the page in my main layout.

Most of my work is backend stuff so I can afford a larger initial download with the advantage of less trips to the server for subsequent js files. It works well for me, but maybe not what you wanted to hear?

But I agree, it’s not a good situation and needs some thought.

In Yii 1, I do this:


if(isset($_GET['ajax']))) {

        Yii::app()->clientScript->scriptMap['jquery.js'] = false;

        Yii::app()->clientScript->scriptMap['jquery.min.js'] = false;

        $this->renderPartial('_form',array('model'=>$model), false, true);

}

I use this approach with even stronger limitation:




if (Yii::app()->request->getIsAjaxRequest()) {

    Yii::app()->clientScript->scriptMap['*.js'] = false;

    Yii::app()->clientScript->scriptMap['*.css'] = false;

}



This is a very frustrating problem, when it comes to including for example widgets, such as gridview or forms with ajax validation.

how about keeping a list of included files in web storage [localStorage and/or sessionStorage] and only include if file is not listed there :unsure:

When I was starting with Yii I searched for solutions and had some success with this problem. I even had a hack to load TinyMCE into jQuery UI dialog with ajax request, see my posts on the yii forum and on the tinymce forum.

But then I found a simple answer to this problem: loading js/css files with ajax request is just wrong.

Don’t we want to make our ajax calls fast and tiny? Or we want to blindly load a bunch of js/css files when doing ajax call?

So in my opinion the best and easiest solution is to include all necessary scripts into the page and do block all scripts (see my post above) during ajax request.

And including all related scripts into the page will be simple in Yii2 using client script bundles feature.

yes this is the solution, that i used with multiple ajax links,requests,posts etc




        Yii::app()->clientScript->scriptMap['jquery.js'] = false;

        Yii::app()->clientScript->scriptMap['jquery.min.js'] = false;

        $this->renderPartial('_form',array('model'=>$model), false, true);



Isn’t this loading scripts via ajax if you have $processOutput=true?

As Maurizio pointed out: CGridView can give you some pains.

I could not get it working, so I ended up putting it in an iframe inside CJuiTabs.

Maybe ugly, but effective for beginners like me.

CGridView in iframe in CJuiTabs

Much bigger problem is that current components make heavy use of manipulating DOM on $(document).ready(…)

and suddenly these built in (mostly jQueryUI) components are not usable with ajax

Was this ever solved or tought of for Yii2? AFAIK we don’t have proccessOutput in renderPartial, making it useless to execute JavaScript in partials.

What is the current solution?