I'm really new to Yii and as a starter, I want to know how to get the value from the textbox when the button is pressed.
<?php CHtml::textField($name,$value,array('submit'=>'')); ?>
<?php echo CHtml::submitButton('Greet!',array(
'submit' => 'message/goodbye')); ?>
Keep your view some thing like
<?php
$form = $this->beginWidget('CActiveForm', array(
'id' => 'aForm',
'htmlOptions' => array('onsubmit'=>"return false;"),
));
?>
<?php echo CHtml::textField('name', 'value'); ?>
<?php echo CHtml::submitButton('Greet!', array('onclick' => 'getValue()'));?>
<?php $this->endWidget(); ?>
And the Action Script for the onclick event is
<script type="text/javascript">
function getValue()
{
$text=$("#aForm").find('input[name="name"]').val();
alert($text);
//$formData=$("#aForm").serialize();
}
</script>
UNDERSTANDING THE BASIC CONCEPT
You have to remember that Yii is an MVC framework ( Model, View Controller ) and the best practice is to keep the entire structure like so. The best way to learn it is from the awesome forum that they have.
Hence, to define a scenario where you would like to save a data/textbox from the form, you would be following the following workflow :
A BASIC WORKFLOW
Assuming that you don't want to save the data in the Database. :
I would be assuming that a basic knowledge of the how the framework works is known. You can check out the guide and the other tutorials if not.
This is a basic workflow in which the data would be taken from the form and validated in the model.
Create a model file in your protected/models folder
Example : Lets name this file as FormData.php
<?php
class FormData extends CFormModel{
public $name;
public $email;
public function rules()
{
return array(
array('name , email','required'), // This rule would make it compulsory for the data to be added.
array('email','email'), // This will check if the email matches the email criteria.
);
}
public function attributeLabels()
{
return array(
'name' => 'Enter your name',
'email' => 'Enter your email',
);
}
}
?>
2. After this , in your protected/FormController.php
Add this :
<?php
class Formdata extends CController{
public function actionCoolForm()
{
$model = new FormData();
if(isset($_POST['FormData'])){
$model->attributes = $_POST['FormData'];
if($model->validate()){
// Do whatever you want to do here.
}
}
$this->render('someview',array('model'=>$model));
}
}
?>
3. Now to add the form in your page is easy :
<?php echo CHtml::form('formdata/coolform','post'); ?>
<?php
echo CHtml::activeTextField($model,'name');
echo CHtml::activeTextField($model,'email');
?>
<?php echo CHtml::endForm(); ?>
Now to add it in the database
The best and the easiest method of adding it in the database is to use the Gii.
But the code is nearly identical, except that the model extends CModel.
I hope that I was able to help.
Related
I have a code in my indext.ctp:
<?php echo $this->Form->input('full_name'); ?>
It gives me
Label is named Full Name my target is Full name
I know i can use:
<?php echo $this->Form->input('full_name', ['label'=>'Full name']); ?>
My question is: Can i do it globaly? Somehow override ucwords(); using in auto generating labels to ucfirst(); ?
Cakephp generate the label text (when not provided) here
It uses Inflector::Humanize() (see the manual)
I guess you can override the default helper (remember that input() is deprecated and you should use control() instead)
class MyFormHelper extends FormHelper
{
public function control($fieldName, array $options = [])
{
if(!isset($options['label']))
$options['label'] = // you own code here;
return parent::control($fieldName, $options);
}
}
then in your AppView.php initialize() you load your helper
$this->loadHelper('Form', [
'className' => 'MyForm',
]);
So when you want to define a custom label you use the 'label' option
<?php echo $this->Form->input('full_name', ['label'=>'Insert the full name here']); ?>
Instead if you don't set the 'label' option
<?php echo $this->Form->input('full_name'); ?>
the helper will use your logic
I tested the behavior and it works in my forms
For example we have this ActiveForm implementation in a sample view:
<?php $form = ActiveForm::begin(); ?>
<?=$form->field($model, 'first_name')->textInput(['maxlength' => true]); ?>
<?=$form->field($model, 'last_name')->textInput(['maxlength' => true]); ?>
<div id="additional-form-fields"></div>
<a href="#" id="load-additional-form-fields">
Load more fields
</a>
<?php ActiveForm::end(); ?>
Now, I want to add more ActiveField / ActiveForm fields inside this form and place them in the #additional-form-fields element with Ajax, I'd do a simple jQuery callback:
$('#load-additional-form-fields').click(function() {
$.get('/site/additional-fields', {}, function(data) {
$('#additional-form-fields').html( data );
});
});
And the action additional-fields inside SiteController would be something as:
public function actionAdditionalFields() {
$model = new User;
return $this->renderAjax('additional-fields', [
'model' => $model,
// I could pass a 'form' => new ActiveForm, here, but it's a big NO-NO!
]);
}
And this works perfectly, only if I don't use any other ActiveField fields inside this action's view:
<?=$form->field($model, 'biography')->textInput(['maxlength' => true]); ?>
<?=$form->field($model, 'country')->textInput(['maxlength' => true]); ?>
<?=$form->field($model, 'occupation')->textInput(['maxlength' => true]); ?>
Of course, I have to pass or instatiate $form somehow in this view, but it's NOT an option to use another ActiveForm::begin() / ActiveForm::end() anywhere inside this view since it will create another <form> tag and thus when I inject the Ajax response, I'll end up with with a <form> inside a <form> ...
Now, my question is as follows: Since I want to use ActiveForm, how can I share an instance of the ActiveForm through out multiple requests?
Is it doable / possible, if so, please help me realize how?
So far I have tried to put $form inside a session, but that's definitelly not working and not an option. Different than that, I've tried when passing parameters to renderAjax:
[
'model' => $model,
'form' => new ActiveForm,
]
In this case I get the following:
Form fields are created as they should with appopriate names and id's.
jQuery is loaded again (at the bottom of the response: <script src="..."> ... you get the idea)
I don't get the generated JavaScript for validation.
Is there anyway to share an instance of $form?
Okay, I have manage to do this, so I'll post the solution here and I'll open an issue on Github - might be useful in future versions.
1. Updates in yii2\widgets\ActiveForm.php
I've added a following property to the ActiveForm class:
/**
* #var boolean whether to echo the form tag or not
*/
public $withFormTag = true;
And I've changed run() method into this (check for // <-- added):
public function run()
{
if (!empty($this->_fields)) {
throw new InvalidCallException('Each beginField() should have a matching endField() call.');
}
$content = ob_get_clean();
if($this->withFormTag) { // <-- added
echo Html::beginForm($this->action, $this->method, $this->options);
} // <-- added
echo $content;
if ($this->enableClientScript) {
$id = $this->options['id'];
$options = Json::htmlEncode($this->getClientOptions());
$attributes = Json::htmlEncode($this->attributes);
$view = $this->getView();
ActiveFormAsset::register($view);
$view->registerJs("jQuery('#$id').yiiActiveForm($attributes, $options);");
}
if($this->withFormTag) { // <-- added
echo Html::endForm();
} // <-- added
}
Thus if we instantiate a form like this:
$form = ActiveForm::begin([
'withFormTag' => false,
]);
It will not echo a <form> tag, but will render all ActiveField items and it will create their respective JavaScript/jQuery validators if $this->enableClientScript = true;.
2. Updates in my local view/file
After applying the previous fix in the base class, I needed to do the following in my view:
<?php $form = ActiveForm::begin([
'withFormTag' => false,
'id' => 'w0',
]); ?>
I had to pass the id parameter since every next instance of the ActiveForm class is incremented by 1, and I want my JavaScript/jQuery validators to be applied to the parent form, which by default starts from 0 -> w0.
And this is what did the trick!
Here's the Github issue as well: https://github.com/yiisoft/yii2/issues/12973
I'm making a language selector and followed this wiki. I can implement the widget, but when I try the dropdown it doesn't make the postback. For the controller I have the idea that the controller should be: components/Controller.php in stead of components/MyController.php. But anyways both don't work. Does anyone know what to do here? I'm missing something about the essentials of catching a postback here i think..
Controller (components/controller.php):
function init()
{
parent::init();
$app = Yii::app();
if (isset($_POST['_lang']))
{
$app->language = $_POST['_lang'];
$app->session['_lang'] = $app->language;
}
else if (isset($app->session['_lang']))
{
$app->language = $app->session['_lang'];
}
Yii::app()->session['_lang'] = 'anders';
}
widget class (components/LangBox.php):
class LangBox extends CWidget
{
public function run()
{
$currentLang = Yii::app()->language;
$this->render('langBox', array('currentLang' => $currentLang));
}
}
widget view (components/views/langBox.php)
<?php echo CHtml::form(); ?>
<div id="langdrop">
<?php echo CHtml::dropDownList('_lang', $currentLang, array(
'en_us' => 'English', 'is_is' => 'Icelandic'), array('submit' => '')); ?>
</div>
<?php echo CHtml::endForm(); ?>
I am sure your code works ok, but are you actually submitting the form? You should really have a jquery that detects when the dropdown changed and submits it to the server and refreshes the page. Everything else is sound.
I have no idea what 'submit'=>'' does.
I have website with few short News , to every News we can write a comment via Form. And there my problem occur.
When i fill my fields in one form, after pressing button, all forms are reloading without saving, and every field in every form must be filled out so they're treated like a one part how to avoid it ?
Additional info ( Info is my main modal with news, it's joined with Com modal)
index.ctp Form
<br><h5>Add comment:</h5><br>
<?php echo $this->Form->create('Com'); ?>
<?php echo $this->Form->input(__('mail',true),array('class'=>'form-control')); ?>
<?php echo $this->Form->input(__('body',true),array('class'=>'form-control')); ?>
<?php $this->request->data['ip'] = $this->request->clientIp(); ?>
<?php $this->request->data['info_id'] = $info['Info']['id']; ?>
<?php echo $this->Form->submit(__('Add comment',true),array('class'=>'btn btn-info')); ?>
<?php $this->Form->end(); ?>
controller ComsController.php
public function add()
{
if($this->request->is('post'))
{
$this->Infos_com->create();
$this->request->data['Infos_com']['ip'] = $this->request->clientIp();
$this->request->data['Infos_com']['id_infos'] = $number;
if($this->Infos_com->save($this->request->data))
{
$this->Session->setFlash(__('Comment is waiting for moderating',true),array('class'=>'alert alert-info'));
return $this->redirect(array('controller'=>'Infos','action'=>'index'));
}
$this->Session->setFlash(__('Niepowodzenie dodania komentarza',true),array('class'=>'alert alert-info'));
return TRUE;
}}
and Model Com.php, i comment lines to avoid neccesity of filling every field in forms
class Com extends AppModel
{
public $belongsTo = array('Info');
/*public $validate = array(
'mail'=>array(
'requierd'=>array(
'rule'=>array('notEmpty'),
'message'=>'Write your email'
)
),
'body'=>array(
'required'=>array(
'rule'=>array('notEmpty'),
'messages'=>'Write smth'
)
)
); */
}
I don't think you can access $this->request->data in a view (the data should be entered with a form, it was not submitted). You should use hidden fields to pass arguments like IP od id... Example:
echo $this->Form->input('Infos_com.client_id', array(
'type' => 'hidden',
'value' => $value
));
If you have multiple forms, it would be useful to separate their fields. For example:
echo $this->Form->input('Infos_com.' . $news_id . '.body', array('label' => __('body')));
This way you will get an array like:
$this->request->data['Infos_com'][$news_id]['body'].
And then you can make your logic in the model.
I need to understand how to build Ajax request in Yii. I searched on the Yii website and found the following article :
http://www.yiiframework.com/wiki/24/
I wrote the code and I tested it on my localhost ? but for some reason it did not work.
For a first attempt I only wanted to do something simple. I wanted to print the result of another action on my page by using Ajax. The text that I want to be displayed is 'Hi'.
This is how mu code looks like for that action:
view/index
<?php
/* #var $this CurrentController */
$this->breadcrumbs=array(
'Current'=>array('/current'),
'index',
);
?>
<div class="form">
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'users-index-form',
'enableAjaxValidation'=>true,
)); ?>
<?php
echo CHtml::dropDownList('country_id','', array(1=>'USA',2=>'France',3=>'Japan'),
array(
'ajax' => array(
'type'=>'POST', //request type
'url'=>CController::createUrl('currentController/dynamiccities'), //url to call.
//Style: CController::createUrl('currentController/methodToCall')
'update'=>'#city_id', //selector to update
//'data'=>'js:javascript statement'
//leave out the data key to pass all form values through
)));
//empty since it will be filled by the other dropdown
echo CHtml::dropDownList('city_id','', array());
?>
<?php $this->endWidget(); ?>
</div><!-- form -->
Controller
<?php
class CurrentController extends Controller
{
public function accessRules()
{
return array(
array('allow', // allow authenticated user to perform 'create' and 'update' actions
'actions'=>array('create','update','dynamiccities'),
'users'=>array('#'),
),
);
}
public $country_id;
public function actionIndex()
{
$this->render('index');
}
public function actionDynamiccities() /// Called Ajax
{
echo CHtml::tag('option',
array('value'=>'2'),CHtml::encode('Text'),true);
}
}
Unfortunately I'm not getting the desired result. What I get is:
drowpdown list contains country array.
another drowpdown list but empty ?!
How should I fix my example code so it would work? Can anyone see what I am doing wrong?
echo CHtml::dropDownList('city_id','', array());
use id as
echo CHtml::dropDownList('city_id','', array('id'=>'city_id'));