Yii2: 'Save Draft' button - validation

I'd like to have a form with the three buttons:
OK button: It runs validation and post data on success.
Cancel button: Skip validation and posting and redirect to the other view.
Save Draft button: Post data without validation.
I know how to implement OK and Cancel buttons, but how to prevent the validation on 'Save Draft' button click?

To bypass the client-end validation just for the draft button, what i would suggest is not to use the submit button for the Draft , use normal button and save the draft using ajax call , this would trigger the validation if you are typing into the field or blur out but not if you hit the draft button. use $.serialize() to get the form inputs and send call to save as draft.

Hope it will help for someone.
Here is the solution:
Add 'Draft Button' as a normal button in your view:
<?= Html::button('Save Draft', ['class' => 'btn btn-default btn-block', 'id' => 'save-draft-btn']) ?>
Add JS file to your view and specify onClick event for the button:
$('#save-draft-btn').on('click', function (e) {
$.ajax({
type: 'POST',
url: draftUrl,
data: $('#report-index').serialize()
});
});
Add the action to your controller:
public function actionSaveDraft($idSupply)
{
//load models like this
$report = \app\models\Reports::findOne($idSupply);
//fill with the POST data
$report->load(Yii::$app->request->post());
//save without validation
$report->save(false);
//inform the user on success saving
Yii::$app->session->setFlash('success', 'Draft Saved');
//redirect to the editing page
return $this->redirect(['index', 'idSupply' => $report->id_supply]);
}

Related

Laravel : Ajax delete with bootstrap modal dialog

I have a bootstrap modal dialog (see image below)
The red danger button (marked by xx) is where the action is happening. When that button is clicked - the uploaded file ( in this case - 2013-09-18_16h40_47.png) should be deleted while the modal dialog box is still open which is not what is happening right now. The download id is not getting passed to the controller method and the modal dialog is closed when the red button is clicked.
UI code :
{{ Form::open( array('route' => 'download.deletedownload','method' => 'post','id' => 'form-add-setting') ) }}
{{Form::hidden('downloadId',$download->id)}}
<button id="downloadDelete" type="submit" class="btn btn-xs btn-danger">xx</button>
{{Form::close()}}
The route looks like this
Route::post('deletedownload', array('uses' => 'DownloadsController#deletedownload', 'as'=>'download.deletedownload'));
and the controller method look like this
public function deletedownload()
{
if(Request::ajax()) {
dd("this is an ajax request");
};
var_dump('i am in the deletedownload method of the DownloadsController class');
$id = Input::get('id');
dd($id);
return Redirect::back();
}
Javascript :
$('#downloadDelete').click(function (e)
{
$.ajax({
type: 'POST',
url: '<?=URL::to('/')?>/deletedownload',
data: 'dataString',
dataType:'json',
success: function(result)
{
console.log(result);
}
})
});
and this is the output
string(66) "i am in the deletedownload method of the DownloadsController class" NULL
Notice that "this is an ajax request" is not getting echoed. Hence i have reasons to believe that is not an ajax request.
Any help would be well appreciated.
thanks
Where is your Javascript ? Ajax request should be sent explicitly with Javascript or jQuery from the client side. I don't know if Ajax is already attached on that modal button ?
UPDATE:
As I can see you are using named route on a server side, but in Ajax request you are pointing to URL ?

ajaxbutton how to prevent refresh of the page

I succeed to use Ajax with Yii framework.
I renderPartial a form from within a list of post.
What I want to do is to prevent refresh when the user click on the ajaxbutton in the form.
In the beginning of the form I used the following code to activate ajax
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'post-form',
'enableAjaxValidation'=>true,
'enableClientValidation'=>true,
)); ?>
and at the end of the page I simply have the ajaxbutton
<?php echo CHtml::ajaxSubmitButton('Save'); ?>
in the action controller I have the following
if(isset($_POST['ajax']) && $_POST['ajax']==='comment-form')
{
echo CActiveForm::validate($comment);
Yii::app()->end();
}
When I click on the ajax button, it saves the data but refresh the page, so it display the form.
What I want is to stay on the page.
Is anyone to help ?
Thank you in advance.
you can prevent the page from refresh, or ask the user if he's sure he want to leave the page by this code:
window.onbeforeunload = function() {
return "Dude, are you sure you want to leave? Think of the kittens!";
}
you can check this question: Prevent any form of page refresh using jQuery/Javascript
I think you have some thing like $this->redirect( ... ));
in your controller after $model->save() , right?
so don't redirect there

Clear validation error message when the value is updated or selected

I have form in yii that validates the form field. When I submit the form it shows the errors.
But when the value of the field with the validation error is updated, the error still present.
I want the message to clear. How should i clear the validation error?
Below the form widget code
<?php $form = $this->beginWidget('CActiveForm', array(
'id'=>'user-form',
'enableAjaxValidation'=>true
)); ?>
In my form I echo the validation error like the code below:
<?php echo $form->error($model, 'firstname'); ?>
I tried the solution from this problem
Trigger Yii field validation onchange of another field
$('#user-form').change(function(){
var settings = $(this).data('settings');
$.each(settings.attributes, function () {
this.status = 2; // force ajax validation
});
$(this).data('settings', settings);
// trigger ajax validation
$.fn.yiiactiveform.validate($(this), function (data) {
$.each(settings.attributes, function () {
$.fn.yiiactiveform.updateInput(this, data, $(this));
});
});
});
But the error message is still not cleared. I have confirmed that the ajax request is sent and there are response as its showed on the firebug console.
[EDIT]
It seems those validation errors for "select" fields are the ones that are not updated/cleared only.
[EDIT]
All the validation errors that are printed/echo after the form is submmitted will not disappear even if the value is supplied or change to satisfy the validation rules.
Place this just above the // trigger ajax validation comment:
$('.errorSummary, .errorMessage').hide();
This should reset the errors before they get re-validated.
In my case I added the code below on the page to remove the red highlight on input field on the form.
$('#user-form select, #user-form input').change(function(){
field = $(this).attr('id');
if($('#'+field+'_em').text() == ''){
$(this).removeClass('error');
}
});
I also add the updateInput function on framework/web/js/source/jquery.yiiactiveform.js so it will remove the validation error for certain field.
if(hasError == false){
$error.toggle(hasError);
$el2 = form.find('#' + attribute.id);
$el2.removeClass(attribute.errorCssClass);
}
I am not sure if this the proper solution but it works for me.
With your form widget code, i don't think ajax validation won't work.
To enable Ajax validation on form you should configure your widget as below,
<?php
$form = $this->beginWidget('CActiveForm', array(
'id'=>'user-form',
'enableAjaxValidation' => true,
'clientOptions' => array(
'validateOnSubmit' => true,
),
));
?>
With this configuration, your form will be validated when form field lost the focus(blur).
Try it, It will give the solution for your problem.

Yii, ajax, Button. How to prevent multiple JS onclick bindings

(First of all English is not my native language, I'm sorry if I'll probably be mistaken).
I've created Yii Web app where is input form on the main page which appears after button click through ajax request. There is a "Cancel" button on the form that makes div with form invisible. If I click "Show form" and "Cancel" N times and then submit a form with data the request is repeating N times. Obviously, browser binds onclick event to the submit button every time form appears. Can anybody explain how to prevent it?
Thank you!
I've had the exact same problem and there was a discussion about it in the Yii Forum.
This basically happens because you are probably returning ajax results with "render()" instead or renderPartial(). This adds the javascript code every time to activate all ajax buttons. If they were already active they will now be triggered twice. So the solution is to use renderPartial(). Either use render the first time only and then renderPartial(), or use renderPartial() from the start but make sure the "processOutput" parameter is only set to TRUE the first time.
Solved!
There was two steps:
First one. I decided to add JS code to my CHtml::ajaxSubmitButton instance that unbind 'onclick' event on this very button after click. No success!
Back to work. After two hours of digging I realized than when you click 'Submit' button it raises not only 'click' event. It raises 'submit' event too. So you need to unbind any event from whole form, not only button!
Here is my code:
echo CHtml::submitButton($diary->isNewRecord ? 'Создать' : 'Сохранить', array('id' => 'newRecSubmit'));
Yii::app()->clientScript->registerScript('btnNewRec', "
var clickNewRec = function()
{
jQuery.ajax({
'success': function(data) {
$('#ui-tabs-1').empty();
$('#ui-tabs-1').append(data);
},
'type': 'POST',
'url': '".$this->createUrl('/diary/newRecord')."',
'cache': false,
'data': jQuery(this).parents('form').serialize()
});
$('#new-rec-form').unbind();
return false;
}
$('#newRecSubmit').unbind('click').click(clickNewRec);
");
Hope it'll help somebody.
I just run into the same problem, the fix is in the line that starts with 'beforeSend'. jQuery undelegate() function removes a handler from the event for all elements which match the current selector.
<?php echo CHtml::ajaxSubmitButton(
$model->isNewRecord ? 'Add week(s)' : 'Save',
array('buckets/create/'.$other['id'].'/'.$other['type']),
array(
'update'=>'#addWeek',
'type'=>'POST',
'dataType'=>'json',
'beforeSend'=>'function(){$("body").undelegate("#addWeeksAjax","click");}',
'success'=>'js:function(data) {
var a=[];
}',
),
array('id'=>'addWeeksAjax')
); ?>
In my example I've added the tag id with value 'addWeeksAjax' to the button generated by Yii so I can target it with jQuery undelegate() function.
I solved this problem in my project this way, it may not be a good way, but works fine for me: i just added unique 'id' to ajax properties (in my case smth like
<?=CHtml::ajaxLink('<i class="icon-trash"></i>',
$this->createUrl('afisha/DeletePlaceAjax',
array('id'=>$value['id'])),
array('update'=>'.data',
'beforeSend' => 'function(){$(".table").addClass("loading");}',
'complete' => 'function(){$(".table").removeClass("loading");}'),
array('confirm'=>"Уверены?",'id'=>md5($value['id']).time()))
?>
).
Of course, you should call renderPartial with property 'processOutput'=true. After that, everything works well, because every new element has got only one binded js-action.
text below copied from here http://www.yiiframework.com/forum/index.php/topic/14562-ajaxsubmitbutton-submit-multiple-times-problem/
common issue...
yii ajax stuff not working properly if you have more than one, and if
you not set unique ID
you should make sure that everything have unique ID every time...
and you should know that if you load form via ajax - yii not working
well with it, cause it has some bugs in the javascript code, with die
and live
In my opinion you should use jQuery.on function. This will fire up event on dynamically changed content. For example: you're downloading some list of images, and populate them on site with new control buttons (view, edit, remove). Example structure could looks like that:
<div id="img_35" class='img-layer'>
<img src='path.jpg'>
<button class='view' ... />
<button class='edit' ... />
<button class='delete' ... />
</div>
Then, proper JS could look like this ( only for delete, others are similiar ):
<script type="text/javascript">
$(document).on('click', '.img-layer .delete', function() {
var imgId = String($(this).parent().attr('id)).split('_')[1]; //obtain img ID
$.ajax({
url: 'http://www.some.ajax/url',
type : 'POST',
data: {
id: imgId
}
}).done({
alert('Success!');
}).fail({
alert('fail :(');
});
}
</script>
After that you don't have to bind and unbind each element when it has to be appear on your page. Also, this solutiion os simple and it's code-clean. This is also easy to locate and modify in code.
I hope, this could be usefull for someone.
Regards
. Simon

form.submit() missed by rails.js UJS observer

In a Rails 3 app, I want to make the browser call a remote function whenever a certain checkbox is toggled. In Rails 2, this was easy to do by passing
:onclick => remote_function(...)
to the checkbox helper. In Rails 3, the remote_* functions are deprecated, so I tried the following workaround:
create a form around the checkbox using form_tag ... :remote => true
submit the form by calling $("dummy_form").submit(); from the onclick handler
In the rails.js file that comes bundled with Rails is an observer that listens for submit events. However, these only seem to be triggered when the user clicks on a submit button, but not when form.submit() is called (so far tested only in FF).
This has the unwanted effect that the submit is then not done in the background via AJAX, but the normal way, so the browser leaves the current site and displays the response from the controller.
Does anyone know a workaround? Maybe a completely different way to get the same functionality?
You can submit the form by calling:
$("dummy_form").request({
onSuccess: function(response) {eval(response)}
});
This will submit the form using AJAX to the url given to form_tag and evaluate received response, so it has to respond with JS. Change the onSuccess implementation if you don't want that.
If the form submission is a workaround, as you say, then instead of submitting the whole form you could also handle the on-click event on the check-box manually and send an AJAX request:
<%= javascript_tag do %>
Event.observe(window, 'load', function() {
$('CHECK_BOX_ID').observe('click', function(event) {
new Ajax.Request('/your/url', {
onSuccess: function(response) {
// yada yada yada
}
})
});
});

Resources