Yii: How to force CGridview to load data via AJAX only? - yii

Is there a way to make a CGridView Not load data on the initial rendering of the view it lives on, and instead make it load the first page with a subsequent AJAX request after the initial page load?
This is mostly for performance optimization. There is a data model that is rather slow behind that CGridView, and I would like to be able to have the page load in a snappy way, then have the data load up a few seconds later with an AJAX request.

You could modify the action as follows:
public function actionIndex() {
$dataProvider = new CActiveDataProvider('User'); // The dataprovider your grid uses
if (!$this->isAjaxRequest()) {
$dataProvider->criteria->addCondition('1 = 0'); // You could also use 0, but I think this is more clear
}
[...]
}
And then in your view in the javascript section:
$(function() { // If you are using jQuery this is executed when the page is loaded
$.fn.yiiGridView.update("{id-of-your-grid-view}");
});

Brewer Gorge was very close, and thanks to his suggested answer, it put me on the right track. This works:
// Controller, after creating $dataProvider, before calling $this->render...
if (!Yii::app()->request->isAjaxRequest) {
$dataProvider->criteria->addCondition('1 = 0');
}
// View
<script type="text/javascript">
$(window).load(function() {
$('#id-of-grid').yiiGridView('update');
});
</script>

Just write your code in controller like this:
$model= new Data('search');
$model->unsetAttributes();
if(isset($_GET['Data']))
$model->attributes = $_GET['Data'];
if (!Yii::app()->request->isAjaxRequest)
$data->id=0; //or something that sure model return empty

Related

How to load view in phalcon without any other contents

I need to load a part of view in phalcon for returning in ajax call. For this i need to set the view in variables. Now what happening is i am getting all templates including header and footer.
You need to disable rest of the view rendering. Example of exact situation (returning JSON response for AJAX)
$viewParams = [
'param1' => '....',
'param2' => '....',
];
$response = new \stdClass();
// Render view into a variable
$this->view->setRenderLevel(\Phalcon\Mvc\View::LEVEL_NO_RENDER);
$response->html = $this->view->getRender('yourTemplateDir', 'yourTemplateName', $viewParams, function($view) {
$view->setRenderLevel(\Phalcon\Mvc\View::LEVEL_ACTION_VIEW);
});
// Disable view
$this->view->disable();
return $this->response->setJsonContent($response);

Rendering results from an API after using a search function with Backbone.js

I am new to Backbone.js and I am trying to create an application that can check if you completed the videos games you control.
I am using an API to retrieve any information about videogames.
I want to be able to search for a game, for example "Zelda". It should then list every Zelda game.
I get stuck because I don't know how to get the search function to work properly with the API and I don't know how to render it properly. I have written a template for the games that should render.
I have no clue what to do know, or if I'm even on the right track. I am not asking for someone to code it completely, I am asking for a step in the right direction.
Let me know if you need more code.
library_view.js
var LibraryView = Backbone.View.extend({
el:$("#games"),
url: url = "http://www.giantbomb.com/api/search/?api_key=[KEY]",
events:{
"keypress input":"findGames"
},
findGames:function(e){
if(e.which == 13){
query = $(".searchfield").val()
field_list = "name,platforms"
resources = "game"
url = url +"&query="+ query +"field_list"+ field_list +"resources"+ resources
}
},
index.html
<input type="search" placeholder="Find a game" class="searchfield">
It looks like you are mashing together a View and a Model.
A view, for instance, shouldn't have URL inside it, it doesn't know what to do with it.
The correct path would be something roughly like so:
var SearchModel = Backbone.Model.extend();
var LibraryView = Backbone.View.extend({
el: $("#games"),
events:{
"keypress input":"findGames"
},
findGames: function(e){
// get query, field_list, resources
var searchModel = new SearchModel()
searchModel.fetch({
url: "http://www.giantbomb.com/api/search/?api_key=[KEY]"+"&query="+ query +"field_list"+ field_list +"resources"+ resources
});
// do something with searchModel
}
});
After the fetch, searchModel will hold the data Backbone Model style.
Let's say the returned value from the AJAX call is:
{
"answer": 42
}
Then:
searchModel.get("answer") // = 42
The SearchModel is just an abstraction here as you don't really need it (you can just ajax it). But I put it to help you understand what Model represents, it basically represents only data... It doesn't know what View is.

How to avoid rendering entire page when using CGridView via AJAX

When creating any ajax request in yii CGridView like (pagination, filtering, ...etc) the result of request will render whole page, how can i avoid that?
I tried to use renderPartial for view but it doesn't work. if this is the solution, how can i do it?
I just need to render the table of GridView not whole page.
Please advice.
In controller:
$this->layout = false;
For me works also $this->renderPartial() in controller instead of $this->render()
if(Yii::app()->request->isAjaxRequest()) $this->renderPartial('view');
else $this->render('view');
U can create class:
class Controller extends CController {
public function beforeAction($action) {
if(Yii::app()->request->isAjaxRequest) $this->layout = false;
return parent::beforeAction($action);
}
}

unobtrusive validation not working with dynamic content

I'm having problems trying to get the unobtrusive jquery validation to work with a partial view that is loaded dynamically through an AJAX call.
I've been spending days trying to get this code to work with no luck.
Here's the View:
#model MvcApplication2.Models.test
#using (Html.BeginForm())
{
#Html.ValidationSummary(true);
<div id="res"></div>
<input id="submit" type="submit" value="submit" />
}
The Partial View:
#model MvcApplication2.Models.test
#Html.TextAreaFor(m => m.MyProperty);
#Html.ValidationMessageFor(m => m.MyProperty);
<script type="text/javascript" >
$.validator.unobtrusive.parse(document);
</script>
The Model:
public class test
{
[Required(ErrorMessage= "required field")]
public int MyProperty { get; set; }
}
The Controller:
public ActionResult GetView()
{
return PartialView("Test");
}
and finally, the javascript:
$(doument).ready(function () {
$.ajax({
url: '/test/getview',
success: function (res) {
$("#res").html(res);
$.validator.unobtrusive.parse($("#res"));
}
});
$("#submit").click(function () {
if ($("form").valid()) {
alert('valid');
return true;
} else {
alert('not valid');
return false;
}
});
The validation does not work. Even if I don't fill any information in the texbox, the submit event shows the alert ('valid').
However, if instead of loading dynamically the view, I use #Html.Partial("test", Model) to render the partial View in the main View (and I don't do the AJAX call), then the validation works just fine.
This is probably because if I load the content dynamically, the controls don't exist in the DOM yet. But I do a call to $.validator.unobtrusive.parse($("#res")); which should be enough to let the validator about the newly loaded controls...
Can anyone help ?
If you try to parse a form that is already parsed it won't update
What you could do when you add dynamic element to the form is either
You could remove the form's validation and re validate it like this:
var form = $(formSelector)
.removeData("validator") /* added by the raw jquery.validate plugin */
.removeData("unobtrusiveValidation"); /* added by the jquery unobtrusive plugin*/
$.validator.unobtrusive.parse(form);
Access the form's unobtrusiveValidation data using the jquery data method:
$(form).data('unobtrusiveValidation')
then access the rules collection and add the new elements attributes (which is somewhat complicated).
You can also check out this article on Applying unobtrusive jquery validation to dynamic content in ASP.Net MVC for a plugin used for adding dynamic elements to a form. This plugin uses the 2nd solution.
As an addition to Nadeem Khedr's answer....
If you've loaded a form in to your DOM dynamically and then call
jQuery.validator.unobtrusive.parse(form);
(with the extra bits mentioned) and are then going to submit that form using ajax remember to call
$(form).valid()
which returns true or false (and runs the actual validation) before you submit your form.
Surprisingly, when I viewed this question, the official ASP.NET docs still did not have any info about the unobtrusive parse() method or how to use it with dynamic content. I took the liberty of creating an issue at the docs repo (referencing #Nadeem's original answer) and submitting a pull request to fix it. This information is now visible in the client side validation section of the model validation topic.
add this to your _Layout.cshtml
$(function () {
//parsing the unobtrusive attributes when we get content via ajax
$(document).ajaxComplete(function () {
$.validator.unobtrusive.parse(document);
});
});
test this:
if ($.validator.unobtrusive != undefined) {
$.validator.unobtrusive.parse("form");
}
I got struck in the same problem and nothing worked except this:
$(document).ready(function () {
rebindvalidators();
});
function rebindvalidators() {
var $form = $("#id-of-form");
$form.unbind();
$form.data("validator", null);
$.validator.unobtrusive.parse($form);
$form.validate($form.data("unobtrusiveValidation").options);
}
and add
// Check if the form is valid
var $form = $(this.form);
if (!$form.valid())
return;
where you are trying to save the form.
I was saving the form through Ajax call.
Hope this will help someone.
just copy this code again in end of modal code
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
;)

ExtJS4 trigger doLayout on store load

I have a grid with store: cdStore defined. The grid's records are edited using a form which is bound to the grid data. When updating a record, I would like for the refreshed records to show in the grid.
Currently I have
handler : function() {
areaForm.getForm().submit({
params: { action: "update" }
});
cdStore.loadPage(cdStore.currentPage);
areaGrid.doLayout();
}
It seems like this fails sometimes and older data remains displayed in the grid - perhaps doLayout() is called before the page is fully loaded.
Can I trigger a doLayout on loadPage somehow?
// ...
cdStore.load({
callback: function(){areaGrid.doLayout();},
page: cdStore.currentPage
});
Update
I would appreciate a line or two with an explanation if you would be so kind
You said that "doLayout() is called before the page is fully loaded" and you were right. So the doLayout must be called after the data is loaded. The one way to do that is to use load method. You can pass array of options into this method:
store.load({
page: 2,
limit: 50,
// and
callback: function(){ /*do something*/ }
});
The function you pass as callback is called exactly after the data is loaded. So doLayout() put into callback produces correct behaviour.