Dynamically show required textfield depending on dropdownlist value - dynamic

Good day. My problem is I have a dropDownlist with three options: A, B, C. What I need to do is to show a textfield depending on what the user chose.
Example: user chose A => it will show textfield AA (which should be required and not empty)
user chose B => it will show textfield BB (which should be required and not empty)
user chose C => it will show textfield CC (which should be required and not empty)
Can anyone please help me? Thank you.
EDIT: It's working now. The only problem now is when an I leave the chosen textfield as blank and it shows the error, the textfield that was shown (the one which is dependent on the value of dropdownlist) disappears or goes back to state display:hidden. This happens right after the 'textfield cannot be blank' error message. The initial chosen value of dropdownList is still there and is still on focus but the textfield disappears.
HERE ARE MY UPDATED CODES:
VIEW:
<div class="row">
<?php echo $form->labelEx($model,'org_type'); ?>
<?php echo $form->dropDownList($model,'org_type', $model::getOrgType(), array('prompt'=>'', 'id'=>'orgType')); ?>
<?php echo $form->error($model,'org_type'); ?>
</div>
<div class="row" style="display:none" id="sec">
<?php echo $form->labelEx($model,'sec_ref'); ?>
<?php echo $form->textField($model,'sec_ref', array('id'=>'secField')); ?>
<?php echo $form->error($model,'sec_ref'); ?>
</div>
<div class="row" style="display:none" id="dti">
<?php echo $form->labelEx($model,'dti_ref'); ?>
<?php echo $form->textField($model,'dti_ref', array('id'=>'dtiField')); ?>
<?php echo $form->error($model,'dti_ref'); ?>
</div>
<div class="row" style="display:none" id="cda">
<?php echo $form->labelEx($model,'cda_ref'); ?>
<?php echo $form->textField($model,'cda_ref', array('id'=>'cdaField')); ?>
<?php echo $form->error($model,'cda_ref'); ?>
</div>
MODEL:
public function addCustomError($attribute, $error) {
$this->customErrors[] = array($attribute, $error);
}
/**
*/
protected function beforeValidate() {
$r = parent::beforeValidate();
if ($this->org_type == 'Single') {//this is the checkbox
$this->validatorList->add(CValidator::createValidator('required',$this,'dti_ref',array()));
}
if ($this->org_type == 'Partnership') {//this is the checkbox
$this->validatorList->add(CValidator::createValidator('required',$this,'sec_ref',array()));
}
if ($this->org_type == 'Corporation') {//this is the checkbox
$this->validatorList->add(CValidator::createValidator('required',$this,'sec_ref',array()));
}
if ($this->org_type == 'Cooperative') {//this is the checkbox
$this->validatorList->add(CValidator::createValidator('required',$this,'cda_ref',array()));
}
foreach ($this->customErrors as $param) {
$this->addError($param[0], $param[1]);
}
return $r;
}
Javascript on View:
<script>
"$('#orgType').change(function(){
if($('#orgType').val() == 'Single')
{
$('#dti').show();
$('#dtiField').addClass('required');
$('#cda').hide();
$('#sec').hide();
}
if(($('#orgType').val() == 'Partnership') || ($('#orgType').val() == 'Corporation'))
{
$('#sec').show();
$('#secField').addClass('required');
$('#dti').hide();
$('#cda').hide();
}
if($('#orgType').val() == 'Cooperative')
{
$('#cda').show();
$('#cdaField').addClass('required');
$('#dti').hide();
$('#sec').hide();
}
return false;
})";

You can try this:
After Every change event of DropDown You can set value to the text Filed ..

Related

adding multiple model records a form within a form - Collecting Tabular Input yii

I am kind of lost. I am following this Collecting Tabular Input. I have a product form, within the product form I have a attribute form, like colors/sizes. I am having trouble understanding this tutorial because of the loop in controller. So I get that it checks the number of records and loop it but what if there's no record. It seems like the tutorial is saying to create a new Model. Yes, of course. But how can you possibly loop it in view if there's no record and telling it to create a new one. Maybe I am not understanding this correctly.
I am just looking to add 3 records, blank or filled. No js to add additional record. Trying to understand this first.
controller:
public function getProdAttr($id) {
$items = array();
if (isset($_POST['ProductAttribute']) ) {
$items = ProductAttribute::model()->findAllByAttributes(array('product_id',$id));
if($items!==null){
foreach ($_POST['ProductAttribute'] as $item) {
$items[] = ProductAttribute::model()->findByPk($item['product_attribute_id']);
}
}
else $items[] = new ProductAttribute();
}
return $items;
}
public function actionUpdate($id)
{
$model=$this->loadModel($id);
$attributes=$this->getProdAttr($id);
if(isset($_POST['ProductAttribute']))
{
$valid=true;
foreach($attributes as $i=>$attribute)
{
if(isset($_POST['ProductAttribute'][$i]))
$attribute->attributes=$_POST['ProductAttribute'][$i];
$valid=$attribute->validate() && $valid;
}
if($valid)
$attributes->save();
}
//stuff from product model
}
view:
//stuff for product model form
<div class="form">
<?php echo CHtml::beginForm(); ?>
<table>
<tr><th>Name</th><th>Description</th><th>Price</th></tr>
<?php foreach($attributes as $i=>$attribute): ?> //lost here, what if there's no records?
<tr>
<td><?php echo CHtml::activeTextField($attribute,"[$i]name"); ?></td>
<td><?php echo CHtml::activeTextArea($attribute,"[$i]description"); ?></td>
<td><?php echo CHtml::activeTextField($attribute,"[$i]cost"); ?></td>
</tr>
<?php endforeach; ?>
</table>
</div>

how to add input value from session using ajaxlink in yii

I am kind of lost on how to do this in my view.
I want to add the quantity. Right now, it adds but how do I get the input value into my ajaxlink?
My controller is using session to add.
<input id="quantity" type="text" value="1" class="span1">
<div id="cart-text">
<?php echo CHtml::ajaxLink(' Add ',
Yii::app()->createUrl('controller/basketAjax',array('id'=>$_GET['id'])),
array('success'=>'function(data){...
controller:
$session=new CHttpSession;
$session->open();
if (!isset(Yii::app()->session['cart']))
{
$quantity = 1;
$session->add('cart',array(
'product_id.'.$id=>array("id"=>$id,
'quantity'=>$quantity)
));
}
else
{
$cart = Yii::app()->session['cart'];
$array = $cart['product_id.'.$id];
if (isset($array)){
$array['quantity']=$array['quantity']+1;
} else {
$t = array('product_id.'.$id=>array("id"=>$id,'quantity'=>$quantity));
array_push($cart,$t);
}
$session->add('cart', $products);
}
you can do this by using keyup function of jquery. First set the id of link as "mylink". Compute the url by using createUrl.
<script type="text/javascript" >
$("#quantity").keyup(function(){
var url=<?php echo Yii::app()->createUrl('controller/basketAjax') ?>;
$("#mylink").attr("href","");
$("mylink").attr("href",url +$(this).val());
});
</script>
Now i explain whats happening above. first i catch the event keyup on input you are using. It will be called each time you press a key on input. Now url=<?php echo Yii::app()->createUrl('controller/basketAjax') ?>; this code is returning you the base url to your action without any parameters being passed.this line $("#mylink").attr("href",""); will set the href of your link to " "( means nothing). Now this line $("mylink").attr("href",url +$(this).val()); is appending the value of the input you are getting from the input.
Remember you have to put the separator in between like
$("mylink").attr("href",url+"/" +"id"+"/"+$(this).val());
Above i have assumed that the href in your case looks like "projectname/index.php/controller/action/id/something". Thats y i have used separators in between but you can customize it according to your needs.
ajaxLink will not work (from what I know), just build it the old fashion way with jquery. Your best solution is actually to put it in a form and submit the form. Something like
<?php
Yii::app()->clientScript->registerCoreScript('yiiactiveform');
$form=$this->beginWidget('CActiveForm', array('action'=>Yii::app()->createUrl('cart/addProduct')));?>
<input type="text" name="quantity" value="1">
<input type="hidden" name="Product_id" value="<?php echo $model->id;?>">
<?php echo CHtml::ajaxSubmitButton('Save',CHtml::normalizeUrl(array('cart/addProduct','render'=>true)),
array(
'dataType'=>'json',
'type'=>'post',
'success'=>'function(data) {
if(data.status=="success"){
$("#formResult").html("form submitted successfully.");
}
else{
$.each(data, function(key, val) {
$("#user-form #"+key+"_em_").text(val);
$("#user-form #"+key+"_em_").show();
});
}
}',
)); ?>
<?php $this->endWidget(); ?><!-- .contact -->
Sorry for the indenting, hard to indent properly here.

i want to show textarea after a specific value chosen from DropDownList

i have an issue .. i have a form that contain a drop down list that have a lot of values
i want when the user choose specific value from drop down a textarea i shown immediately .. i know i will have to use javascript but i dont know how
this is my Code :
<div class="row">
<?php echo $form->labelEx($model,'type'); ?>
<?php echo $form->dropDownList($model,'type',$model->getTypeOptions()); ?>
<?php echo $form->error($model,'type'); ?>
</div>
<div class="row">
<?php echo "<b>Data</b> : <i> Use WhiteSpaces or , to enter values</i> "; ?><br/>
<?php echo $form->textArea($model, 'data', array('rows'=>10, 'cols'=>50)); ?>
<?php echo $form->error($model, 'data'); ?>
</div>
i want this textarea only shown when the user choose value (ex: checkboxtlist from dropdown)
i searched and found that in
$form->dropDownList($model,'type',$model->getTypeOptions());
we can but array parameter inside dropDownList .. but i dont really know what excatly to write in this array
any help ?
Do like below:
<?php echo $form->dropDownList($model,'type',$model->getTypeOptions(),array('id'=>'myDropDown')); ?>
<?php echo $form->textArea($model, 'data', array('rows'=>10, 'cols'=>50,'id'=>'myTextArea')); ?>
Now, What you need is to create an Ajax request.
<script>
$('#myDropDown').on('change', function() {
$.ajax({
url: "<?php echo $this->createUrl('controller/test'); ?>",
dataType: 'html',
type: 'POST',
data: {dropDownValue: $(this).val()},
success: function(data, textStatus, jqXHR) {
$('#myTextArea').val(data);
}‌
});
});
Note that test is a action in your controller.(replace with your own names).
Then, Create the action:
public function actionTest() {
if (Yii::app()->request->isAjaxRequest) {
$dropDownValue = Yii::app()->request->getPost('dropDownValue');
if ($dropDownValue === 'A VALUE YOU WANT TO COMPARE WITH') {
echo 'SOME THING YOU WANT';
}
Yii::app()->end();
}
}
To know more, we say that if value of dropdown changed, call an ajax request in order to send dropdown value to server. Then if our value was what we want, we would do something. Finally in success function which means that ajax successfully returned response we change our textArea's value with what server(test action) sent to us.

Yii/Giix - Standard 2 Column Layout

The code below shows the two column layout in Yii. The $content variable holds a search form and a gridview form.
I'm trying to get the gridview to appear to the right of the Advanced Search Section in this two-column grid format. Kind of brain farting here, where in the standard Giix structure is the variable $content given it's contents? I didn't see it in the basemodel or controller.
Thanks in advance.
<?php /* #var $this Controller */ ?>
<?php $this->beginContent('//layouts/main'); ?>
<div class="span-24">
<div id="content">
<?php echo $content; ?>
</div><!-- content -->
</div>
<div class="span-5 last">
<div id="sidebar">
<?php
$this->beginWidget('zii.widgets.CPortlet', array(
'title'=>'Operations',
));
$this->widget('zii.widgets.CMenu', array(
'items'=>$this->menu,
'htmlOptions'=>array('class'=>'operations'),
));
$this->endWidget();
?>
</div><!-- sidebar -->
</div>
<?php $this->endContent(); ?>
$content is given its content when your controller call $this->render() at the end of its action.
public function actionIndex() {
// renders the view file 'protected/views/site/index.php'
// using the default layout 'protected/views/layouts/main.php'
[some code...]
$this->render('index');
}
The process involved is a bit obfuscated but you can easily trace it down by setting a breakpoint and looking at the stack in your debugger.
You can also read the code :
render() is a method of the CController class :
public function render($view, $data = null, $return = false) {
if ($this->beforeRender($view)) {
$output = $this->renderPartial($view, $data, true); // (1)
if (($layoutFile = $this->getLayoutFile($this->layout)) !== false)
$output = $this->renderFile($layoutFile, array('content' => $output), true); // (2)
[snip...]
}
}
(1) If no error occurs before rendering, the view is populated and its HTML code assigned to $output : $output = $this->renderPartial($view, $data, true);
(2) Then, unless you stated in your action that the view must not be decorated by the layout by colling $this->setLayout(false), the Decorator pattern is applied and the internal view set in the layout :
$output = $this->renderFile($layoutFile, array('content' => $output), true)
Here, you shall notice that the second argument is an array : array('content' => $output)
renderfile() is a method of CBaseController which, at some point, will call
public function renderInternal($_viewFile_, $_data_ = null, $_return_ = false) {
// we use special variable names here to avoid conflict when extracting data
if (is_array($_data_))
extract($_data_, EXTR_PREFIX_SAME, 'data'); // (1)
else
$data = $_data_;
if ($_return_) {
ob_start();
ob_implicit_flush(false);
require($_viewFile_); // (2)
return ob_get_clean();
}
else
require($_viewFile_);
}
And that's where your answer lies :
(1) $data is still our array('content' => $output). The extract function will build and initialize variables from this array, namely your $content variable.
(2) The layout file is now required. $content exists in its scope, as well, of course, as your controller wich lies behind $this
Use a grid layout in the specific view. It should something like
<div class='span-10'>
//search form
</div>
<div class='span-9'>
//grid
</div>

Yii: model attribute's comments/hints

I need to have comments/hints for some fields in my Form. My idea is to describe it in model, just like attributeLabels. How can I do it?
And then it would be ideal, if the Gii Model (and Crud) generator would take it directly from mysql column's comment
So I see two questions here:
Describe hints in the model and display on the form.
Get hints from mysql comment
Displaying Hints from Model
Here's a slightly modified version of the default login.php file generated by Yiic
<div class="form">
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'login-form',
'enableClientValidation'=>true,
'clientOptions'=>array(
'validateOnSubmit'=>true,
),
)); ?>
<p class="note">Fields with <span class="required">*</span> are required.</p>
<div class="row">
<?php echo $form->labelEx($model,'username'); ?>
<?php echo $form->textField($model,'username'); ?>
<?php echo $form->error($model,'username'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'password'); ?>
<?php echo $form->passwordField($model,'password'); ?>
<?php echo $form->error($model,'password'); ?>
<p class="hint">
Hint: You may login with <kbd>demo</kbd>/<kbd>demo</kbd> or <kbd>admin</kbd>/<kbd>admin</kbd>.
</p>
</div>
<div class="row rememberMe">
<?php echo $form->checkBox($model,'rememberMe'); ?>
<?php echo $form->label($model,'rememberMe'); ?>
<?php echo $form->error($model,'rememberMe'); ?>
</div>
<div class="row buttons">
<?php echo CHtml::submitButton('Login'); ?>
</div>
<?php $this->endWidget(); ?>
</div><!-- form -->
Let's move that password hint into the model by adding a attributeHints() method and a getHint() method to the LoginForm.php model.
/**
* Declares attribute hints.
*/
public function attributeHints()
{
return array(
'password'=>'Hint: You may login with <kbd>demo</kbd>/<kbd>demo</kbd> or <kbd>admin</kbd>/<kbd>admin</kbd>.',
);
}
/**
* Return a hint
*/
public function getHint( $attribute )
{
$hints = $this->attributeHints();
return $hints[$attribute];
}
As you can see, we;ve moved the hint text from the view into the model and added a way to access it.
Now, back in login.php, let's add the hint tag based on data from the model.
<div class="row">
<?php echo $form->labelEx($model,'password'); ?>
<?php echo $form->passwordField($model,'password'); ?>
<?php echo $form->error($model,'password'); ?>
<?php echo CHtml::tag('p', array('class'=>'hint'), $model->getHint('password')); ?>
</div>
So now we've changed the hardcoded hint into a generated element populated with data from the model.
Now, moving on to the second question.
Getting hints from mySQL comments
Unforunately, I am not fammiliar enough with Gii to know how to automatically generate the hints from mySQL comments. However, getting the mySQL comment data into the model is fairly easy.
To do this we can use the following mySQL query
SHOW FULL COLUMNS FROM `tbl_user`
So let's add the comment to the password field
ALTER TABLE `tbl_user`
CHANGE `password` `password` VARCHAR( 256 )
CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL
COMMENT 'Hint: You may login with <kbd>demo</kbd>/<kbd>demo</kbd> or <kbd>admin</kbd>/<kbd>admin</kbd>.';
And let's add the code to fetch it into our attributeHints() method.
/**
* Declares attribute hints.
*/
public function attributeHints()
{
$columns= Yii::app()->db->createCommand('SHOW FULL COLUMNS FROM `tbl_user`')->queryAll();
$comments=array();
foreach($columns as $column){
if( isset( $column['Comment'] ) )
{
$comments[ $column['Field'] ] = $column['Comment'];
}
}
//Add any hardcoded hints here
$hints = array(
'username'=>'Enter username above',
);
//Return merged array
return array_merge( $comments, $hints );
}
We now have two ways to set comments, through mySQL comments or through hard coded statements.
Let's update our login.php file quick to include hints of both types.
<div class="row">
<?php echo $form->labelEx($model,'username'); ?>
<?php echo $form->textField($model,'username'); ?>
<?php echo $form->error($model,'username'); ?>
<?php echo CHtml::tag('p', array('class'=>'hint'), $model->getHint('username')); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'password'); ?>
<?php echo $form->passwordField($model,'password'); ?>
<?php echo $form->error($model,'password'); ?>
<?php echo CHtml::tag('p', array('class'=>'hint'), $model->getHint('password')); ?>
</div>
And that's it!
Now our login page will look like this, with a username hint from the model and a password hint from the mySQL comment.
As of Yii-1.1.13, a new attribute, comment, has been added to CMysqlColumnSchema which is defined in parent CDbColumnSchema:
comment of this column. Default value is empty string which means that no comment has been set for the column. Null value means that RDBMS does not support column comments at all (SQLite) or comment retrieval for the active RDBMS is not yet supported by the framework.
So we can use it to access the comment. Somewhat like this:
$modelObject->tableSchema->columns['column_name']->comment
// or if you are doing this within your model use
$this->tableSchema->columns['column_name']->comment
Note that the tableSchema is already set when any CActiveRecord model is constructed or even if the static model is used, so there are no new queries executed when we access the property.
A sample implementation within your model:
class MyModel extends CActiveRecord {
// hints array will store the hints
public $hints=array();
public function init() {
parent::init();
$this->hints=self::initHints($this);
}
public static function initHints($model) {
$comments=array();
foreach ($model->tableSchema->columns as $aColumn){
if(!empty($aColumn->comment))
$comments["$aColumn->name"]=$aColumn->comment;
}
return $comments;
}
public static function model($className=__CLASS__) {
$model=parent::model($className);
$model->hints=self::initHints($model);
return $model;
}
}
Now you can access hints as:
$model = new MyModel;
$single_column_hint=$model->hints['column_name'];
$model = MyModel::model();
$single_column_hint=$model->hints['column_name'];
For doing this through gii templates, you just need to copy the above code to your custom model code template, read the guide to see how this can be done.
I would recommend having the code in a custom base class, from which you can derive your active records.