Delete row clistview doesn't work anymore - yii

I have a delete function in a CListView, which used to work, but doesn't anymore.
In the CListView I have:
echo CHtml::link('<img src="images/delete.png" />',
$this->createUrl('persoon/delete',array('id'=>$data->id)),
array(// for htmlOptions
'onclick'=>' {'.CHtml::ajax( array(
'beforeSend'=>'js:function(){if(confirm("Are you sure you want to delete?"))return true;else return false;}',
'success'=>"js:function(html){ alert('removed'); }"
)).
'return false;}',// returning false prevents the default navigation to another url on a new page
'class'=>'delete-icon')
);
The controller is unedited:
public function actionDelete($id)
{
$this->loadModel($id)->delete();
// if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser
if(!isset($_GET['ajax']))
$this->redirect(array('index'));
}
There is no error, but it just doesn't remove an item when clicked. Does someone know what happened here?

Related

Phalcon\Mvc\View\Simple::render() in mailer causing WSOD

I have a simple controller action that creates a Guest record and renders a template.
// First bind the form to our Guest:
$form->bind( $_POST, $guest );
// Validate and save, or show error messages
if( $form->isValid($_POST, $guest) ) {
if( $guest->save($_POST) ) {
$this->view->setMainView( 'confirm' );
}
}
This works fine before I add any mailer stuff. However, when I add an event handler inside the Guest model which happens to render a template, the controller renders a WHITE SCREEN OF DEATH instead of my confirm template.
In Guest model:
public function afterCreate() {
return GuestMailer::sendEmailConfirmation( $this );
}
In GuestMailer class:
public static function sendEmailConfirmation( $guest ) {
// create/configure $email message
$view = $guest->getDI()->get('simpleView');
$view->render( // Works without this call...
'confirmation_email',
array( 'guest' => $guest )
);
$content = $view->getContent();
$email->content( $content );
return $email->send();
}
Note that when I remove the above call to render(), the confirm template is rendered successfully.
I thought components in Phalcon were supposed to be highly decoupled? Why is rendering a completely different template causing my controller's view to get messed up? How can I avoid this?
I think this problem is caused by a peculiar configuration of the templating service, in a normal workflow it doesn't causes issues, they appears when you need to render "manually" a template as in your case, you can refer to this PhalconPHP forum discussion linked, in particular the answer refered by the link anchor:
http://forum.phalconphp.com/discussion/109/manually-render-separate-file-template-#C12015

"Controller method not found." Laravel error. How can I figure out what method was called that it couldn't find?

I started using Laravel a month ago. Trying to make a page with one form on it and I keep getting a "Controller method not found." error. There is only one form on the page and that method is being called fine and making the query that I want. It does redirect to the same page with that form, /dashboard/edit/module.
It would be awesome if I could see what method is not being found or where it is in my code. Any ideas how I can do this? Someone mentioned App::error or messing with Log::error in global.php but I can't get any more information shown.
Edit:
I found that the form action is only being found if I upload a video to the form. Other then that it gives me the same error. Here is the controller method of this form. The page with this form is /dashboard/edit/module and I would like to reload that page after this runs.
public function postSection(){
$path = public_path() . "/videos/";
$filename = uniqid() . '.mp4';
$file_path = $path . $filename;
$moduleID = Input::get('moduleID');
if(!Input::hasFile('video')){
return Redirect::back()->with('error', 'Must enter a valid video file.');
}else{
try {
Input::file('video')->move($path, $filename);
$section = New Section;
$section->module_id = $moduleID;
$section->video = $file_path;
$section->save();
//I was trying to use this instead of View::make to stop form resubmission
//return Redirect::to('/dashboard/edit/module')->with('moduleID', $moduleID);
return View::make('forms.editMod')->with('moduleID', $moduleID);
}catch ( Exception $e){
return Redirect::back()->with('error', 'Unable to save the video file.');
}
}
}
Edit: And my routes.php
//Route for the home page
Route::get('/', function(){ return View::make('home'); });
//Controllers
Route::controller('dashboard/edit', "ContentController");
Route::controller('user', "UserController");
Route::group(array('before'=> 'auth|dash'), function(){
//dashboard home
Route::get('/dashboard', function(){ return View::make('dashboard');});
//dashboard subs
Route::get('dashboard/modules', function(){ return View::make('forms.module');});
Route::get('dashboard/users', function(){ return View::make('users');});
Route::get('dashboard/reporting', function(){ return View::make('reporting');});
//user pages
Route::get('dashboard/register', function(){ return View::make('forms.register');});
Route::post('dashboard/edit/user', array('before'=>'csrfajax', function(){
$id = Input::get('userID');
$user = User::find($id);
return View::make('forms.editUser')->with('user', $user);
}));
});
And the form...
{{ Form::open(array('files' => true, 'action' => 'ContentController#postSection', 'id' => 'sectionform')) }}
<fieldset>
{{ Form::label('Video (mp4)') }}
{{ Form::hidden('moduleID', $module->id)}}
{{ Form::file('video', array('id' => 'video', 'class' => 'form-control')) }}<br>
{{ Form::submit('Save') }}
</fieldset>
{{ Form::close() }}
In routes.php, to reach this method you're using Route::controller, which results in RESTful routing. If the browser's HTTP request used the POST action, you'd correctly be routed to public function postSection(){}. But if the HTTP request used GET, which is the default for web browsing, especially when no data is being submitted by the browser, Laravel would be looking for a method called public function getSection(){}. This would explain why when you're uploading something (i.e. using POST), you reach the page, but otherwise you don't.
See the official documentation for the full low-down on implicit routing: http://laravel.com/docs/controllers#implicit-controllers

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>
;)

Pagination with Search form not working

I am implementing pagination on my search result, on the very first page it is working fine, but the problem is when i click on 2 for second page results, it displays empty page.
In view i have:
$this->widget('zii.widgets.CListView', array('dataProvider'=>$dataProvider,
'itemView'=>'_listing'));
while in my controller i have:
if (isset($_POST)
{
(......)
$dataProvider=new CArrayDataProvider($results,array(
'keyField' => 'brand_id',
'pagination'=>array(
'pageSize'=>5,
)));
//echo "<pre>"; print_r($dataProvider);exit;
$this->render('listing',array('dataProvider'=>$dataProvider, 'post' => $_POST));
}
The $results contains my search results, controller has a check if post is set or not, so when request for load of second page is sent to listing action, the post data is not set, so it does not enters the code and displays nothing.
How to make post data available to action when call for second page is done?
try this
$this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_listing',
'ajaxUpdate'=>'#divViewPanel',
'enablePagination'=>true
));

Yii CListview -> pagination and AjaxLink/ajaxButton

I have problems regarding with pagination and Ajax form.
Here is my code for Controller:
$dataProvider = new CActiveDataProvider('User', array(
'pagination'=>array(
'pageSize'=>10,
),
));
$this->render('users',array(
'dataProvider'=>$dataProvider,
));
For view -> users:
$this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_user',
);
For render _users:
echo CHtml::ajaxLink($text, $this->createUrl('admin/deleteuser',array('id'=>$data->iduser)), array('success'=>"js:function(html){ alert('remove') }"), array('confirm'=>_t('Are you sure you want to delete this user?'), 'class'=>'delete-icon','id'=>'x'.$viewid));
if i have 15 rows in a database it will only show 10 and will generate a pagination (ajaxUpdate = true) for next 5. The first 10 rows has no problem with the ajaxLink because the clientscript was generated but problem is the when I move to the next page, the ajaxLink is not working because its not generated by the pagination .
any idea? thanks
An alternate method, check this post in the yii forum. So your code will become like this:
echo CHtml::link($text,
$this->createUrl('admin/deleteuser',array('id'=>$data->iduser)),
array(// for htmlOptions
'onclick'=>' {'.CHtml::ajax( array(
'beforeSend'=>'js:function(){if(confirm("Are you sure you want to delete?"))return true;else return false;}',
'success'=>"js:function(html){ alert('removed'); }")).
'return false;}',// returning false prevents the default navigation to another url on a new page
'class'=>'delete-icon',
'id'=>'x'.$viewid)
);
Your confirm is moved to jquery's ajax function's beforeSend callback. If we return false from beforeSend, the ajax call doesn't occur.
Another suggestion, you should use post variables instead of get, and also if you can, move the ajax call to a function in the index view, and just include calls to the function from the all links' onclick event.
Hope this helps.
Not fully sure, but given past experiences I think the problem is in the listview widget itself.
If the owner of the widget is a Controller, it uses renderPartial to render the item view.
Renderpartial has, as you may or may not know, a "processOutput" parameter which needs to be set to TRUE for most of the AJAX magic (its FALSE by default).
So perhaps you can try to just derive a class of the listview and add a copy in there of "renderItems()". There you would have to change it so that it calls renderPartial with the correct parameters.
In the widget Clistview, I added afterAjaxUpdate
$jsfunction = <<< EOS
js:function(){
$('.delete-icon').live('click',function(){
if(confirm('Are you sure you want to delete?'))
{
deleteUrl = $(this).attr('data-href');
jQuery.ajax({'success':function(html){ },'url':deleteUrl,'cache':false});
return false;
}
else
return false;
});
}
EOS;
$this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'id'=>'subscriptionDiv',
'itemView'=>'_subscription',
'afterAjaxUpdate'=>$jsfunction,
'viewData'=>array('is_user'=>$is_user,'all'=>$all),
'htmlOptions'=>($dataProvider->getData()) ? array('class'=>'table') : array('class'=>'table center'),
)
);
and in the _user just added attribute data-href
<?php echo CHtml::ajaxLink($text, $this->createUrl('admin/deletesubscription',array('id'=>$data->idsubscription)),
array('success'=>"js:function(html){ $('#tr{$viewid}').remove(); }"),
array('confirm'=>_t('Are you sure you want to unsubscribe?'),
'class'=>'delete-icon',
'id'=>'x'.$viewid,
'data-href'=>$this->createUrl('admin/deletesubscription',array('id'=>$data->idsubscription))
)); ?>
try
$this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_user',
'enablePagination' => true,
);
if this doesn't solve, try including the total number of records in the data provider options as -
'itemCount' => .....,