Mform SELECT - Moodle - moodle

Is there mform select tag, when option is selected so that it highlights and stick to the selected one and select more options without the use of control key to select. I tried with selectMulitple, where it allows holding control key to select the options.
$select = $mform->addElement('select', 'course', get_string('course', 'core_course'), $options);
$mform->addHelpButton('course', 'course', 'core_course');
$mform->addRule('course', null, 'required', null, 'client');
$mform->setType('course', PARAM_INT);
$select->setMultiple(true);

Short answer is no. You need to use the control key to select multiple items in a select.
You could use a series of checkboxes though, something like this:
$courses = core_course_category::get(0)->get_courses(
array('recursive' => true, 'sort' => array('fullname' => 1)));
foreach ($courses as $course) {
$mform->addElement('advcheckbox', "courses[{$course->id}]",
format_string($course->fullname), null, array('group' => 1));
}
$this->add_checkbox_controller(1);
Then in your edit code, use something like this
for each($formdata->courses as $courseid => $selected) {
if ($selected) {
// User selected this course.
} else {
// User unselected this course.
}
}

Related

How to set Navigation menu based on User type - SOCIALENGINE

How to set Navigation based on user type/profile type logged in.
All I could do is - set auth for specific user type
if (!$this->_helper->requireAuth()->setAuthParams('<module>', null, 'create')->isValid())
return;
But with this the menu will be still available
For example - If a Candidate logs in I should be able to hide create JOB menu.
Please give some insights on this. Thanks for your time!
Please create a function in menu.php in plugin of your module.You can check user module and also add a entry 'engine4_core_menuitems'. In table find your menu add entry in plugin _Plugin_Menus. Below function will have naming convention as your your function Name.
public function onMenuInitialize_JobMenu()
{
$viewer = Engine_Api::_()->user()->getViewer();
//assuming level id 4 for candidate
if( !$viewer->level_id == '4') {
return false;
}
return array(
'label' => 'create Job',
'route' => 'job_general',
'params' => array(
'action' => 'groupsms'
)
);
}

Conditional Validation in ZF2

I have a form which starts with a Select with two options. There are several other fields, some of which are required for the first Select option, and the others required for the second Select option.
In the view, I'm using the Select to show/hide the relevant/irrelevant fields. Most of these fields are required when their option in the Select is selected.
What is the best way to only validate the fields that are relevant to whatever is selected in the Select?
In your controller, you could do something like that (the key is the form's setValidationGroup function):
//GET THE FORM
$form = $this->getServiceLocator()->get( '<FORM_NAME>' );
//GET THE POSTED DATA
$request = $this->getRequest();
$data = get_object_vars( $request->getPost() );
//DEPENDING ON THE SELECT VALUE, VALIDATE THIS OR THAT FIELDS
if ( $data[ 'SELECT_NAME' ] === 'A' ) {
$form->setValidationGroup( array( 'INPUT_A', 'INPUT_B' ) );
} else {
$form->setValidationGroup( array( 'INPUT_C', 'INPUT_D' ) );
}
//PERFORM THE FORM VALIDATION
if ( !$form->isValid() ) {
//FORM IS WRONG
( ... )
}
//FORM IS OK
( ... )

Yii CJuiAutoComplete for Multiple values

I am a Yii Beginner and I am currently working on a Tagging system where I have 3 tables:
Issue (id,content,create_d,...etc)
Tag (id,tag)
Issue_tag_map (id,tag_id_fk,issue_id_fk)
In my /Views/Issue/_form I have added a MultiComplete Extension to retrieve multiple tag ids and labels,
I have used an afterSave function in order to directly store the Issue_id and the autocompleted Tag_ids in the Issue_tag_map table, where it is a HAS_MANY relation.
Unfortunately Nothing is being returned.
I wondered if there might be a way to store the autocompleted Tag_ids in a temporary attribute and then pass it to the model's afterSave() function.
I have been searching for a while, and this has been driving me crazy because I feel I have missed a very simple step!
Any Help or advices of any kind are deeply appreciated!
MultiComplete in Views/Issue/_form:
<?php
echo $form->labelEx($model, 'Tag');
$this->widget('application.extension.MultiComplete', array(
'model' => $model,
'attribute' => '', //Was thinking of creating a temporary here
'name' => 'tag_autocomplete',
'splitter' => ',',
'sourceUrl' => $this->createUrl('Issue/tagAutoComplete'),
// Controller/Action path for action we created in step 4.
// additional javascript options for the autocomplete plugin
'options' => array(
'minLength' => '2',
),
'htmlOptions' => array(
'style' => 'height:20px;',
),
));
echo $form->error($model, 'issue_comment_id_fk');
?>
AfterSave in /model/Issue:
protected function afterSave() {
parent::afterSave();
$issue_id = Yii::app()->db->getLastInsertID();
$tag; //here I would explode the attribute retrieved by the view form
// an SQL with two placeholders ":issue_id" and ":tag_id"
if (is_array($tag))
foreach ($tag as $tag_id) {
$sql = "INSERT INTO issue_tag_map (issue_id_fk, tag_id_fk)VALUES(:issue_id,:tag_id)";
$command = Yii::app()->db->createCommand($sql);
// replace the placeholder ":issue_id" with the actual issue value
$command->bindValue(":issue_id", $issue_id, PDO::PARAM_STR);
// replace the placeholder ":tag_id" with the actual tag_id value
$command->bindValue(":tag_id", $tag_id, PDO::PARAM_STR);
$command->execute();
}
}
And this is the Auto Complete sourceUrl in the Issue model for populating the tags:
public static function tagAutoComplete($name = '') {
$sql = 'SELECT id ,tag AS label FROM tag WHERE tag LIKE :tag';
$name = $name . '%';
return Yii::app()->db->createCommand($sql)->queryAll(true, array(':tag' => $name));
actionTagAutoComplete in /controllers/IssueController:
// This function will echo a JSON object
// of this format:
// [{id:id, name: 'name'}]
function actionTagAutocomplete() {
$term = trim($_GET['term']);
if ($term != '') {
$tags = issue::tagAutoComplete($term);
echo CJSON::encode($tags);
Yii::app()->end();
}
}
EDIT
Widget in form:
<div class="row" id="checks" >
<?php
echo $form->labelEx($model, 'company',array('title'=>'File Company Distrubution; Companies can be edited by Admins'));
?>
<?php
$this->widget('application.extension.MultiComplete', array(
'model' => $model,
'attribute' => 'company',
'splitter' => ',',
'name' => 'company_autocomplete',
'sourceUrl' => $this->createUrl('becomEn/CompanyAutocomplete'),
'options' => array(
'minLength' => '1',
),
'htmlOptions' => array(
'style' => 'height:20px;',
'size' => '45',
),
));
echo $form->error($model, 'company');
?>
</div>
Update function:
$model = $this->loadModel($id);
.....
if (isset($_POST['News'])) {
$model->attributes = $_POST['News'];
$model->companies = $this->getRecordsFromAutocompleteString($_POST['News']
['company']);
......
......
getRecordsFromAutocompleteString():
public static cordsFromAutocompleteString($string) {
$string = trim($string);
$stringArray = explode(", ", $string);
$stringArray[count($stringArray) - 1] = str_replace(",", "", $stringArray[count($stringArray) - 1]);
$criteria = new CDbCriteria();
$criteria->select = 'id';
$criteria->condition = 'company =:company';
$companies = array();
foreach ($stringArray as $company) {
$criteria->params = array(':company' => $company);
$companies[] = Company::model()->find($criteria);
}
return $companies;
}
UPDATE
since the "value" porperty is not implemented properly in this extension I referred to extending this function to the model:
public function afterFind() {
//tag is the attribute used in form
$this->tag = $this->getAllTagNames();
parent::afterFind();
}
You should have a relation between Issue and Tags defined in both Issue and Tag models ( should be a many_many relation).
So in IssueController when you send the data to create or update the model Issue, you'll get the related tags (in my case I get a string like 'bug, problem, ...').
Then you need to parse this string in your controller, get the corresponding models and assigned them to the related tags.
Here's a generic example:
//In the controller's method where you add/update the record
$issue->tags = getRecordsFromAutocompleteString($_POST['autocompleteAttribute'], 'Tag', 'tag');
Here the method I'm calling:
//parse your string ang fetch the related models
public static function getRecordsFromAutocompleteString($string, $model, $field)
{
$string = trim($string);
$stringArray = explode(", ", $string);
$stringArray[count($stringArray) - 1] = str_replace(",", "", $stringArray[count($stringArray) - 1]);
return CActiveRecord::model($model)->findAllByAttributes(array($field => $stringArray));
}
So now your $issue->tags is an array containing all the related Tags object.
In your afterSave method you'll be able to do:
protected function afterSave() {
parent::afterSave();
//$issue_id = Yii::app()->db->getLastInsertID(); Don't need it, yii is already doing it
foreach ($this->tags as $tag) {
$sql = "INSERT INTO issue_tag_map (issue_id_fk, tag_id_fk)VALUES(:issue_id,:tag_id)";
$command = Yii::app()->db->createCommand($sql);
$command->bindValue(":issue_id", $this->id, PDO::PARAM_INT);
$command->bindValue(":tag_id", $tag->id, PDO::PARAM_INT);
$command->execute();
}
}
Now the above code is a basic solution. I encourage you to use activerecord-relation-behavior's extension to save the related model.
Using this extension you won't have to define anything in the afterSave method, you'll simply have to do:
$issue->tags = getRecordsFromAutocompleteString($_POST['autocompleteAttribute'], 'Tag', 'tag');
$issue->save(); // all the related models are saved by the extension, no afterSave defined!
Then you can optimize the script by fetching the id along with the tag in your autocomplete and store the selected id's in a Json array. This way you won't have to perform the sql query getRecordsFromAutocompleteString to obtain the ids. With the extension mentioned above you'll be able to do:
$issue->tags = CJSON::Decode($_POST['idTags']);//will obtain array(1, 13, ...)
$issue->save(); // all the related models are saved by the extension, the extension is handling both models and array for the relation!
Edit:
If you want to fill the autocomplete field you could define the following function:
public static function appendModelstoString($models, $fieldName)
{
$list = array();
foreach($models as $model)
{
$list[] = $model->$fieldName;
}
return implode(', ', $list);
}
You give the name of the field (in your case tag) and the list of related models and it will generate the appropriate string. Then you pass the string to the view and put it as the default value of your autocomplete field.
Answer to your edit:
In your controller you say that the companies of this model are the one that you added from the Autocomplete form:
$model->companies = $this->getRecordsFromAutocompleteString($_POST['News']
['company']);
So if the related company is not in the form it won't be saved as a related model.
You have 2 solutions:
Each time you put the already existing related model in you autocomplete field in the form before displaying it so they will be saved again as a related model and it won't disapear from the related models
$this->widget('application.extensions.multicomplete.MultiComplete', array(
'name' => 'people',
'value' => (isset($people))?$people:'',
'sourceUrl' => array('searchAutocompletePeople'),
));
In your controller before calling the getRecordsFromAutocompleteString you add the already existing models of the model.
$model->companies = array_merge(
$model->companies,
$this->getRecordsFromAutocompleteString($_POST['News']['company'])
);

Zend form populate method

I have a Zend form below is the code
public function editAction()
{
try
{
$data = Zend_Auth::getInstance()->getStorage()->read();
$this->view->UserInfo = $data['UserInfo'];
$this->view->Account = $data['Account'];
$UserEditForm = $this->getUserEditForm();
$this->view->UserEditForm = $UserEditForm;
$params = $this->_request->getParams();
if ($params['user'])
{
$UserResult = $this->_user_model->getUserData($params['user']);
$UserAddressResult = $this->_user_model->getAddressData($params['user']);
$UserInfo = Array(
'UserId' => $UserResult['user_id'],
'EmailAddress' => $UserResult['email'],
'UserName' => $UserResult['username'],
'Title' => $UserResult['Title'],
'FirstName' => $UserResult['firstname'],
'LastName' => $UserResult['lastname'],
'Gender' => $UserResult['gender'],
'DateOfBirth' => date('m/d/Y', strtotime($UserResult['dateofbirth'])),
'AddressLine1' => $UserAddressResult['address_1'],
'AddressLine2' => $UserAddressResult['address_2'],
'City' => $UserAddressResult['city'],
'State' => $UserAddressResult['state_id'],
'PostalCode' => $UserAddressResult['postcode'],
'Country' => $UserAddressResult['country_id'],
'CompanyName' => $UserAddressResult['company'],
'WorkPhone' => $UserAddressResult['workphone'],
'HomePhone' => $UserAddressResult['homephone'],
'Fax' => $UserAddressResult['fax'],
'IsDashboardUser' => $UserResult['is_dashboard_user']
);
$UserEditForm->populate($UserInfo);
$this->view->UserEditForm = $UserEditForm;
}
if ($this->_request->isPost())
{
$values = $this->_request->getPost();
unset($values['Save']);
if ($UserEditForm->isValid($values))
{
$Modified_date = date('Y-m-d H:i:s');
$UserData = $this->_user_model->CheckEmail($values['EmailAddress']);
$UpdateData = $this->_user_model->UpdateUserData($UserData['user_id'], $values, $Modified_date, $data['UserId']);
if ($UpdateData != null)
{
return $this->_helper->redirector('userlist','index','user');
}
}
}
}
catch (Exception $exception)
{
echo $exception->getCode();
echo $exception->getMessage();
}
}
Because my form elements names are different then my table field names i have to declare a Array $UserAddressResult see above code to match the table field name with form element name.
Is there a another way to populate form without declaring this array.
Please don't suggest that i have to keep my table field name and form element name same. I cannot do that as per our naming convention standards.
Your naming convention is inconsistent. If it were consistent, you could perhaps use a simple regular expression to transform column names. But you can't, so you will have to do it manually one way or the other.
If you need to construct this array of values in more than one place in your code, you should consider moving the logic to the form itself (extend it with a public function populateFromUserAndResult($userResult, $userAddress)) or an action helper.
We decided to keep same name of form elements as per our table fields name. For now this is the only solutions i feel. if i come across any other solutions in future will update here...
Thanks for all your replies....

How to do a select with Zend Framework from a form?

im trying make a form with zend, and i do know how to do a select from a form
public function init()
{
$this->addElement("text","titulo",array(
"label" => "Titulo"
));
$this->setAttrib("id", "enviarNoticia");
$this->setAttrib("class", "FormEnviarNoticia");
$this->setMethod("post");
$this->addElement("textarea","noticia",array());
$this->addElement("submit","Enviar",array());
$this->addElement("multiselect", "categories",array(
"label" => "Categories",
"required" => false,
));
}
How to add options and item selected?
Instead of trying to get the data from the form itself, you should get the data from the model/database in your controller and assign the values to the form from the controller.
// In a controller
// get the options from your model or database into an array
$options = array('name' => 'value', 'name2' => 'value2', 'name3' => 'value3');
$form = new Application_Form_Form();
$form->getElement('categories')->setMultiOptions($options); // set the $options as the options for the categories multiselect
if ($this->getRequest()->isPost()) {
if ($this->form->isValid($this->getRequest()->getPost())) {
// form passed validation
}
} else { // form was not submitted
// to set default value(s) for the select
$form->getElement('categories')->setValue(array('name2', 'name3'));
}