In my Yii web application, any type of Ajax call like Ajax validation, Ajax for dependent dropdown etc.... Is not working.
My codes are,
In my form page:
<?php
$form = $this->beginWidget('CActiveForm', array(
'id' => 'workdetails-form',
'enableClientValidation' => true,
'clientOptions' => array(
'validateOnChange' => true,
'validateOnSubmit' => true,
),
// Please note: When you enable ajax validation, make sure the corresponding
// controller action is handling ajax validation correctly.
// There is a call to performAjaxValidation() commented in generated controller code.
// See class documentation of CActiveForm for details on this.
'enableAjaxValidation' => true,
'htmlOptions' => array('enctype' => 'multipart/form-data'),
));
?>
in controller:
public function actionCreate() {
$model = new Workdetails;
// Uncomment the following line if AJAX validation is needed
$this->performAjaxValidation($model);
if (isset($_POST['Workdetails'])) {
$model->attributes = $_POST['Workdetails'];
if ($model->validate()) {
if ($model->save()) {
$this->redirect(array('create'));
}
}
}
$this->render('create', array(
'model' => $model,
));
}
For dependant dropdown:
<div class="form-group col-sm-6">
<?php echo $form->label($model, 'designationid', array('class' => 'req')); ?>
<?php
$designation = CHtml::listData(Designation::model()->findAll(), 'designationid', 'designation_name');
echo $form->dropDownList($model, 'designationid', $designation, array(
'class' => 'form-control',
'prompt' => 'Please Select',
'ajax' => array(
'type' => 'POST',
'url' => $this->createUrl('workdetails/Fetchemployee'), // here for a specific item, there should be different URL
'update' => '#' . CHtml::activeId($model, 'employeeid'), // here for a specific item, there should be different update
'data'=>array('designationid'=>'js:this.value'),
)));
?>
<?php echo $form->error($model, 'designationid', array('class' => 'school_val_error')); ?>
</div>
How to solve this...
Please help me..
Arya I had the same problem with Yii1 and i gave up using yii-ajax validation cause i could not find a way to fix it. First make sure you have initialize/ register Yii-js file these are
yiiactiveform and yii.js
If you don't have these files on your project, it means you have not registered them. To register the core JS file proceed with this config in your main.
'clientScript' => array(
'scriptMap' => array(
'jquery.js' => true,
'jquery.min.js' => true,
),
),
or if that doesn't work use this on your main view in the header section.
Yii::app()->clientScript->registerCoreScript('jquery');
You can also add it to your base controller which is at components/Controller.php
public function init() {
parent::init();
Yii::app()->clientScript->registerCoreScript('jquery');
}
On your view have this when creating your forms. It will help in placing the error messages. to your elements
<?php
$form = $this->beginWidget('CActiveForm', array(
'id' => 'patient-registration-form',
'enableClientValidation' => True,
'enableAjaxValidation' => FALSE,
'clientOptions' => array(
'validateOnSubmit' => true,
'afterValidate' => 'js:function(form, data, hasError) {
if(hasError) {
for(var i in data) $("#"+i).parent().addClass("has-error");
return false;
}
else {
form.children().removeClass("has-error");
return true;
}
}',
'afterValidateAttribute' => 'js:function(form, attribute, data, hasError) {
if(hasError) $("#"+attribute.id).parent().addClass("has-error");
else $("#"+attribute.id).parent().removeClass("has-error");
$("#"+attribute.id).parent().addClass("has-success");
}'
),
'htmlOptions' => array(
'class' => 'form-horizontal form-bordered form-row-stripped',
),
));
?>
alternatively use Yii2 it has fixed alot of stufff and if you are loading the current page with ajax you need to render the the whole page including the js file again. since when you use renderPartial it doesn't initalize the js files hence no js scripts will work, including validation.
Related
In my Yii application, Yii's default Ajax is not working. Also default Ajax validation is not working. Has this been an installation problem or any other problem. How to enable Yii's default Ajax.
In my controller,
public function actionCreate() {
$model = new Company;
// Uncomment the following line if AJAX validation is needed
$this->performAjaxValidation($model);
if (isset($_POST['Company'])) {
$company = Company::model()->findAll();
if (count($company) === 0) {
$model->attributes = $_POST['Company'];
$uploadedFile = CUploadedFile::getInstance($model, 'logo');
if (isset($uploadedFile)) {
$fileName = date('Ymdhis') . '_' . $uploadedFile->name; // $timestamp + file name
$model->logo = $fileName;
}
if ($model->validate()) {
if ($model->save()) {
if (isset($uploadedFile)) {
$uploadedFile->saveAs(Yii::app()->basePath . '/../banner/' . $fileName);
}
$this->redirect(array('create'));
}
}
} else {
Yii::app()->user->setFlash('error', 'Company details is already exists.');
}
}
$this->render('create', array(
'model' => $model,
));
}
In view page,
<?php
$form = $this->beginWidget('CActiveForm', array(
'id' => 'company-form',
'enableClientValidation' => true,
'clientOptions' => array(
'validateOnChange' => true,
'validateOnSubmit' => true,
),
// Please note: When you enable ajax validation, make sure the corresponding
// controller action is handling ajax validation correctly.
// There is a call to performAjaxValidation() commented in generated controller code.
// See class documentation of CActiveForm for details on this.
'enableAjaxValidation' => true,
'htmlOptions' => array('enctype' => 'multipart/form-data'),
));
?>
<div class="form-group">
<?php echo $form->label($model, 'company_name', array('class' => 'req')); ?>
<?php echo $form->textField($model, 'company_name', array('class' => 'form-control')); ?>
<?php echo $form->error($model, 'company_name', array('class' => 'school_val_error')); ?>
</div>
Please help me.
Thanks...
Yii has no default AJAX. This is a technology based on JavaScript language. By default Yii includes a jQuery library which provided some methods for easy manipulations with AJAX. If you want use it on your page, you should add this string:
Yii::app()->clientScript->registerCoreScript('jquery');
You can add this string to your main layout, for example into top of /views/layouts/main.php`
I'm not getting it!.. Can please someone explain, how to translate form labels? A simple example would be great.
Thank you in advance!
class Search\Form\CourseSearchForm
...
class CourseSearchForm extends Form {
...
public function __construct(array $cities) {
parent::__construct('courseSearch');
...
$this->add(array(
'name' => 'city',
'type' => 'Zend\Form\Element\Select',
'options' => array(
'label' => 'Stadt',
'value_options' => $this->cities,
'id' => 'searchFormCity',
),
));
...
}
}
view script /module/Search/view/search/search/search-form.phtml
<?php echo $this->form()->openTag($form); ?>
<dl>
...
<dt><label><?php echo $form->get('city')->getLabel(); ?></label></dt>
<dd><?php echo $this->formRow($form->get('city'), null, false, false); ?></dd>
...
</dl>
<?php echo $this->form()->closeTag(); ?>
<!-- The formRow(...) is my MyNamespace\Form\View\Helper (extends Zend\Form\View\Helper\FormRow); the fourth argument of it disables the label. -->
The module/Application/config/module.config.php is configured:
return array(
'router' => ...
'service_manager' => array(
'factories' => array(
'translator' => 'Zend\I18n\Translator\TranslatorServiceFactory',
),
),
'translator' => array(
'locale' => 'de_DE',
'translation_file_patterns' => array(
array(
'type' => 'gettext',
'base_dir' => __DIR__ . '/../language',
'pattern' => '%s.mo',
),
),
),
'controllers' => ...
'view_manager' => ...
);
I also edited my view and use the FormLabel view helper:
<dt><label><?php echo $this->formLabel($form->get('city')); ?></label></dt>
Furthermore I debugged the FormLabel at the place, where the tranlator is used (lines 116-120) -- seems to be OK.
But it's still not working.
EDIT
The (test) items for labels, I added to the de_DE.po file manually, are tranlated. The ZF2 side problem was actually, that I was using $form->get('city')->getLabel() instead of $this->formlabel($form->get('city')) in th view script.
The problem is now, that the labels are not added to the de_DE.po file. But it's not a ZF2 issue anymore, so I've accept Ruben's answer and open a new Poedit question.
Instead of using:
<?php echo $form->get('city')->getLabel(); ?>
You should use the formlabel view helper. This helper automatically uses your translator during rendering if you have inserted it in your ServiceManager. Most likely you will have it in your Application's module module.config.php:
'service_manager' => array(
'factories' => array(
'translator' => 'Zend\I18n\Translator\TranslatorServiceFactory',
),
),
'translator' => array(
'locale' => 'en_US',
'translation_file_patterns' => array(
array(
'type' => 'gettext',
'base_dir' => __DIR__ . '/../language',
'pattern' => '%s.mo',
),
),
),
Once you do use the formlabel view helper:
echo $this->formLabel($form->get('city'));
And of course make sure your translations are in your .po file.
i think your problem is that you label are not detected by poedit (or similar tool), so you have to add them manually to your poedit catalogs (.po)
to make your label strings detected by tools like poedit, your strings need to be used inside a translate() function or _() (other function can be added in Catalog/properties/sources keyword)
as the _() function is not user in ZF2 (today) so a tiny hack is to add a function like this in your index.php (no need to modify anything, this way, in poedit params):
// in index.php
function _($str)
{
return $str;
}
and in your code, just use it when your strings are outside of a translate function
//...
$this->add(array(
'name' => 'city',
'type' => 'Zend\Form\Element\Select',
'options' => array(
'label' => _('myLabel') , // <------ will be detected by poedit
'value_options' => $this->cities,
'id' => 'searchFormCity',
),
));
//...
or like this if you prefer
$myLabel = _('any label string'); // <--- added to poedit catalog
//...
'options' => array(
'label' => $myLabel ,
'value_options' => $this->cities,
'id' => 'searchFormCity',
),
#Ruben says right!
Me I use PoEdit to generate my *.mo files and to be sure to get all translations in the file, I create somewhere (in view for example) a file named _lan.phtml with all text to be translated :
<?php echo $this->translate("My label");
... ?>
Of course, Poedit has to be configured to find my keywords. check this to how to configure it
All solutions don't use the power of ZF2. You must configure your poedit correctly :
All things are here :
http://circlical.com/blog/2013/11/5/localizing-your-twig-using-zend-framework-2-applications
I supposed the $form->addVlidator functions works as some front-end form checking thing, however when I add it, even the input is invalid, it seems the form is still being submited.
Or I was wrong, it's more a controller-side checking, which means the form will submit the data whatever then the server sides returns the error message?
My code works like this.
Form class:
<?php
class Application_Form_Test extends Zend_Form
{
public function init()
{
$this->setName('stdForm');
//$this->setMethod('post');
//$this->addDecorator('HtmlTag', array('tag' => 'div', 'class' => 'my-lovely-form'));
$this->setAttrib('enctype', 'multipart/form-data');
$this->setAction('somewhere')
->setMethod('post');
$username = $this->createElement('text', 'name', array('label' => 'Username:'));
$username->addValidator('alnum')
->addValidator('regex', false, array('/^[a-z]+/'))
->addValidator('stringLength', false, array(9, 20, 'messages'=>'Cannot be more than 9 chars'))
->setRequired(true)
->addFilter('StringToLower');
$email = $this->createElement('text', 'email', array('label' => 'E-mail'));
$email->addValidator('StringLength', false, array(8))
->setRequired(true);
$password = $this->createElement('password', 'pass1', array('label' => 'Password'));
$password->addValidator('StringLength', false, array(6))
->setRequired(true);
$password2 = $this->createElement('password', 'pass2', array('label' => 'Repeat password'));
$password2->addValidator('StringLength', false, array(6))
->setRequired(true);
$message = $this->createElement('textarea', 'message', array('label' => 'Message'));
$message->addValidator('StringLength', false, array(6))
->setRequired(true)
->setAttrib('COLS', '40')
->setAttrib('ROWS', '4');
$captcha = new Zend_Form_Element_Captcha('foo', array(
'label' => "human?",
'captcha' => 'Figlet',
'captchaOptions' => array(
'captcha' => 'Figlet',
'wordLen' => 6,
'timeout' => 300,
),
));
// Add elements to form:
$this->addElement($username)
->addElement($email)
->addElement($password)
->addElement($password2)
->addElement($message)
->addElement($captcha)
// use addElement() as a factory to create 'Login' button:
->addElement('submit', 'send', array('label' => 'Form sender'));
}
}
Controller code:
public function aboutAction()
{
$this ->_helper->layout->disableLayout();
$form = new Application_Form_Test();
$this->view->testForm = $form;
}
View file:
<?php echo $this->testForm;?>
The second: "the form will submit the data whatever then the server sides returns the error message". In order to do this you must call $form->isValid($this->_request->getPost()) in your action.
If it is not valid then you need to send data back to the user:
$form->populate($this->_request->getPost());
$this->view->form = $form;
For client side validation you can use http://docs.jquery.com/Plugins/Validation
When users click on a button (with id graph), I'd like to fill the default Drupal content div (<div class="content">) with a graphael instance.
The JavaScript:
jQuery(document).ready(function($) {
$('#toggle #graph').click(function() {
$.ajax({
url: "http://www.mysite.com/?q=publications/callback",
type: 'POST',
data: {
'format' : 'graph'
},
success: function(response) {
$('div#content div.content').html(response);
}
});
});
});
The PHP:
$items['publications/callback'] = array(
'type' => MENU_CALLBACK,
'title' => 'All Publications Callback',
'page callback' => '_process_publications',
'page arguments' => array(t('journal')),
'access callback' => TRUE,
);
which leads to the page callback: (I'm concerned with the if code block)
function _process_publications($venue) {
if( isset($_POST['format']) && $_POST['format'] == "graph" ){
_make_bar_chart($venue);
}
elseif( isset($_POST['format']) && $_POST['format'] == "list" ) {
_make_list($venue);
}
else{
return("<p>blah</p>");
}
}
and finally the function called within the callback function:
function _make_bar_chart($venue) {
// get active database connection
$mysql = Database::getConnection();
// if connection is successful, proceed
if($mysql){
// do stuff
$graphael = array(
'method' => 'bar',
'values' => $ycoordinates,
'params' => array(
'colors' => $colors,
'font' => '10px Arial, sans-serif',
'opts' => array(
'gutter' => '20%',
'type' => 'square',
),
'label' => array(
'values' => $xcoordinates,
'isBottom' => true,
),
),
'extend' => array(
'label' => array(
'values' => $ycoordinates,
'params' => array('attrText' => array(
'fill' => '#aaa',
'font' => '10px Arial, sans-serif',
)),
),
),
);
return theme('graphael', $graphael);
}
// else, connection was unsuccessful
else{
print("<p>bad connection</p>");
}
}
THE PROBLEM: returning a theme doesn't really send anything back to the AJAX request (unlike print statements). I tried to print the theme, but that produces a white screen of death. How would I generate the graph without printing something?
Much thanks to nevets on the Drupal forums for the helpful hint: http://drupal.org/node/1664798#comment-6177944
If you want to use AJAX with Drupal, you are best off actually using Drupal-specific AJAX-related functions. In my theme's page.tpl.php file, I added the following to make the links which would call AJAX:
<?php
// drupal_add_library is invoked automatically when a form element has the
// '#ajax' property, but since we are not rendering a form here, we have to
// do it ourselves.
drupal_add_library('system', 'drupal.ajax');
// The use-ajax class is special, so that the link will call without causing
// a page reload. Note the /nojs portion of the path - if javascript is
// enabled, this part will be stripped from the path before it is called.
$link1 = l(t('Graph'), 'ajax_link_callback/graph/nojs/', array('attributes' => array('class' => array('use-ajax'))));
$link2 = l(t('List'), 'ajax_link_callback/list/nojs/', array('attributes' => array('class' => array('use-ajax'))));
$link3 = l(t('Create Alert'), 'ajax_link_callback/alert/nojs/', array('attributes' => array('class' => array('use-ajax'))));
$output = "<span>$link1</span><span>$link2</span><span>$link3</span><div id='myDiv'></div>";
print $output;
?>
When one of the links above is clicked, the callback function is called (e.g. ajax_link_callback/graph):
// A menu callback is required when using ajax outside of the Form API.
$items['ajax_link_callback/graph'] = array(
'page callback' => 'ajax_link_response_graph',
'access callback' => 'user_access',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
.. and the callback to which it refers:
function ajax_link_response_graph($type = 'ajax') {
if ($type == 'ajax') {
$output = _make_bar_chart('journal');
$commands = array();
// See ajax_example_advanced.inc for more details on the available commands
// and how to use them.
$commands[] = ajax_command_html('div#content div.content', $output);
$page = array('#type' => 'ajax', '#commands' => $commands);
ajax_deliver($page);
}
else {
$output = t("This is some content delivered via a page load.");
return $output;
}
}
This replaces any HTML within <div class="content"> with the graphael chart returned from _make_bar_chart above.
I am trying to have a Checkbox "Agree TOS".
If the Checkbox is not checked, I want to put out a Flash Message.
How do I do this?
My View:
<?php
echo $form->create('Item', array('url' => array_merge(array('action' => 'find'), $this->params['pass'])));
echo $form->input('Search', array('div' => false));
echo $form->submit(__('Search', true), array('div' => false));
echo $form->checkbox('tos', array('label' => false, 'value'=>1)).' Agree TOS';
echo $form->error('tos');
echo $form->end();
?>
My Model:
var $check = array(
'tos' => array(
'rule' => array('comparison', 'equal to', 1),
'required' => true,
'allowEmpty' => false,
'on' => 'index',
'message' => 'You have to agree TOS'
));
This seems working for me. Hope it will help.
In model:
'tos' => array(
'notEmpty' => array(
'rule' => array('comparison', '!=', 0),
'required' => true,
'message' => 'Please check this box if you want to proceed.'
)
In view:
<?php echo $this->Form->input('tos', array('type'=>'checkbox', 'label'=>__('I confirm I have read the privacy statement.', true), 'hiddenField' => false, 'value' => '0')); ?>
Model
'agreed' => array(
'notempty' => array(
'rule' => array('comparison', '!=', 0),//'checkAgree',
'message' => ''You have to agree TOS'',
'allowEmpty' => false,
'required' => true,
'last' => true, // Stop validation after this rule
'on' => 'signup', // Limit validation to 'create' or 'update' operations
),
),
View
<?php echo $this->Form->input('agreed',array('value'=>'0'),array('type'=>'checkbox', 'label'=>'Agree to TOS')); ?>
basically, you add the rule "notEmpty" for this field to the public $validate array of the model.
this way an error will get triggered on Model->validates() if the checkbox has not been checked.
maybe some overhead in your case, but if you happen to use it more often try a DRY (dont repeat yourself) approach. you can also use a behavior for this to use this clean and without tempering too much with the model/controller:
// view form
echo $this->Form->input('confirmation', array('type'=>'checkbox', 'label'=>__('Yes, I actually read it', true)));
and in the controller action
// if posted
$this->Model->Behaviors->attach(array('Tools.Confirmable'=>array('field'=>'confirmation', 'message'=>'My custom message')));
$this->Model->set($this->data);
if ($this->Model->validates()) {
// OK
} else {
// Error flash message here
}
1.x:
https://github.com/dereuromark/tools/blob/1.3/models/behaviors/confirmable.php
for 2.x:
https://github.com/dereuromark/cakephp-tools/blob/2.x/Model/Behavior/ConfirmableBehavior.php
3.x: https://github.com/dereuromark/cakephp-tools/blob/master/src/Model/Behavior/ConfirmableBehavior.php
details:
http://www.dereuromark.de/2011/07/05/introducing-two-cakephp-behaviors/
I believe you need try save it into your model to catch your tos rules. I should do something like =
if(!$mymodel->save()){
// catch error tos.
}
$this->ModelName->invalidFields() returns an array of fields that failed validation.
You could try and search this for the tos field, and output a message if the key exists.
~untested (I'm not sure off the top of my head the exact structure of the invalidFields return array.
$failed_fields = $this->ModelName->invalidFields();
if(array_key_exists('tos', $failed_fields)) {
$this->Session->setFlash('Please accept the terms and conditions');
}
you don't even have to have validation rule for tos, just check that at the controller before saving the data.
if($this->data['Model']['tos']==1){
// save data
}else{
//set flash
}