I have got this error while using the code below in DetailView of Yii 2.
Object of class Closure could not be converted to string
The code is:
[
'format' => 'raw',
'attribute' => 'title',
'value' => function($model1, $key) {
if ($model1->book->language == 1) {
$m = "<p class='n'>" . $model1->book->title . "</p>";
} else {
$m = $model1->book->title;
}
return $m;
},
'contentOptions' => ['class' => 'text-center'],
'headerOptions' => ['class' => 'text-center']
],
Can you guys help me?
DetailView does not take closure like GridView for value, just string. Change it to:
'value' => $model1->book->language == 1
? "<p class='n'>" . $model1->book->title . "</p>"
: $model1->book->title,
Related
I'm trying to implement a multiple models form using the form-wizard widget, with Profile as main model and few others as linked ones. When I select the entity type field for the main model, I would like to change the linked model for the next step, basing on the value of entity type field.
I have tried with this code:
Create Form Code
$modelUrlReletedModelsCreate = Profile::urlRelatedModelCreate();
$urlLinkedProfile = Url::to(['create']);
echo FormWizard::widget([
'formOptions'=>[
'id'=>'profile_form',
'enableClientValidation'=>true,
'enableAjaxValidation'=>true,
'validationUrl' => Url::to(['profile-models-validation'])
],
'theme' => FormWizard::THEME_MATERIAL_V,
'steps' => [
//step 1
[
'model' => $model,
'title' => \Yii::t('app', 'Profile'),
'fieldConfig' => [
'only' => ['entity_type_id', 'profile_type_id'],
'entity_type_id' => [
'widget' => Select2::class,
'options' => [
'data' => EntityType::arrayNamesList(),
'options' => ['placeholder' => \Yii::t('app','Select an element')],
'pluginEvents' => ['select2:select'=>'function(e){;'
. 'var type = $("#pr-ty-sel").val();'
. 'var profile= "'.($model->profile_id ? : "no").'";'
. '$.ajax({ method: "GET",'
. 'url:"'.$urlLinkedProfile.'",'
. 'data:{ entity_text : e.params.data.text,'
. 'entity_id : e.params.data.id,'
. 'profile_type_id : type,'
. 'profile_id : profile},'
. 'success: function(data){'
. '$("#profile_form").html(data);'
. '}'
. '});}'],
],
],
'profile_type_id' =>[
'widget' => Select2::class,
'options' => [
'data' => \app\models\ProfileType::arrayNamesList(),
'options' => ['placeholder' => \Yii::t('app','Select an element'),'id'=>'pr-ty-sel'],
],
]
],
'description' => \Yii::t('app', 'Add Profile Type Data'),
'formInfoText' => \Yii::t('app', 'Fill all fields'),
],
//step 2 I want ot change here $linkedModel
[
'model' => [$model,$linkedModel],
'title' => \Yii::t('app', 'Personal Data'),
'description' => \Yii::t('app', 'Insert Personal Data'),
],
]
]);
Controller Action Create Code
public function actionCreate($profileId = NULL)
{
if($profileId AND $profileId !== 'no'){
$model = $this->findModel($profileId);
}else{
$model = new Profile();
}
$profileLinkedModel = new ProfilePrivate();
$renderMethod = 'render';
if (Yii::$app->request->isAjax) {
$entityText = \Yii::$app->request->get('entity_text');
$entity_id = \Yii::$app->request->get('entity_id');
$profileTypeId = \Yii::$app->request->get('profile_type_id');
$profileId = \Yii::$app->request->get('profile_id');
//Utility function to clean the entity text (remove number and special characters)
$entityTextCleaned = \app\components\Utility::cleanString($entityText);
if ($entityTextCleaned == 'private') {
$profileLinkedModel = new ProfilePrivate();
} elseif ($entityText == 'company') {
$profileLinkedModel = new ProfileCompany();
} else {
//#TODO
return FALSE;
}
$model->entity_type_id = $entity_id;
$model->profile_type_id = $profileTypeId;
$profileLinkedModel->profile_id = $model->profile_id;
Yii::$app->response->format = Response::FORMAT_JSON;
$renderMethod = 'renderAjax';
}
//extra table field used to enable custom rule in model
$model->createFullProfile = TRUE;
if ($model->load(Yii::$app->request->post())) {
return $this->redirect(['view', 'id' => $model->profile_id]);
}
return $this->$renderMethod('create', [
'model' => $model,
'profileLinkedModel' => $profileLinkedModel,
]);
}
When I select a field for entity type field, the server runs the ajax request on select event, but when it ends the other form field is not more selectable. So, in other words, after the ajax request I'm unable to select the profile type field. If I try to select the profile type field before the entity type field I can go to next step, but load always the default model.
I want that a text in gridview is link that sends this text to filter of the same column.
so far I'm doing this way:
'columns'=>[
...
[
'attribute'=>'colname',
'value'=>function($data){
return Html::a($data->colname,Yii::$app->request->url.'&MymodelSearch[colname]='.$data->colname);
},
],
...
]
but it's ugly and doesn't always work
'columns' => [
// ...
[
'attribute' => 'colname',
'format' => 'raw',
'value' => function ($data, $key, $index, $column) {
if ($data->colname)
return
"<span onclick=\""
. (new \yii\web\JsExpression("setFilterColname('"
. Html::encode($data->colname) . "');"))
. "\">"
. \yii\helpers\Html::encode($data->colname)
. "</span>";
}
// ...
]
Add this at bottom of view file
<?php
$this->registerJs("
function setFilterColname(filter_value) {
$('input[name=\"MymodelSearch[colname]\"]').val(filter_value);
$('#w0').yiiGridView('applyFilter');
// #w0 is ID of grid to be submited to filter
}
", $this::POS_END, 'set-filter-colname');
?>
I am using kartik select2 library. I have the modal which is loading in the page from ajax with renderAjax. The modal has the select2 dropdown.
The problem is it load the js but do not load the css files of select2.
echo $form->field($assign_model, 'applicant_id')->widget(Select2::classname(), [
'data' => $applicant,
'attribute' => 'applicant_id',
'options' => ['placeholder' => 'Select an applicant', 'multiple' => 'multiple', 'style' => "width:100%"],
'pluginEvents' => [
"select2:selecting" => "function() { "
. "no_position = $('body').data('no_position');"
. "if(no_position>= " . $model->no_of_persons . "){alert('You can select only " . $model->no_of_persons . " applicant(s)');return false;} }",
"select2:select" => "function() { "
. "no_position = $('body').data('no_position');"
. "$('body').data('no_position',++no_position);}",
"select2:unselect" => "function() { "
. "no_position = $('body').data('no_position');"
. "$('body').data('no_position',--no_position);}",
],
'pluginOptions' => [
'allowClear' => true,
]
]);
I have used use kartik\file\FileInput; (extension) for saving multiple images from single form submit.
The images are save locally but are not saving in the database.
Here is my Model Code media.php
namespace app\models;
use yii\web\UploadedFile;
class Media extends \yii\db\ActiveRecord
{
public function rules(){
return [
[['title'], 'file', 'skipOnEmpty' => false, 'extensions' => ['gif', 'jpg', 'png', 'jpeg', 'JPG', 'JPEG', 'PNG', 'GIF'], 'checkExtensionByMimeType' => false ,'maxFiles' => 4, 'maxSize' => 1024 * 1024 * 1024],
[['extension'], 'string', 'max' => 6],
];
}
Controller code:
if ($mediamodel->load ( Yii::$app->request->post () )) {
$title = UploadedFile::getInstances ( $mediamodel, 'title' );
foreach ($title as $key => $file) {
$file->saveAs(Yii::$app->basePath . '/web/images/hotel/'. $file->baseName . '.' . $file->extension);}
foreach ($title as $key => $file){
echo $mediamodel->title."*********";
$mediamodel->title = $file->baseName . '.' . $file->extension;
echo " \Title: ".$mediamodel->title;
$mediamodel->save ();
}
}
My view code:
use kartik\file\FileInput;
$form = ActiveForm::begin([ 'layout' => 'horizontal', {label}\n{beginWrapper}\n{input}\n{hint}\n{error}\n{endWrapper}",
'fieldConfig' => ['horizontalCssClasses' => ['label' => 'col-md-3','offset' => 'col-md-offset-2','wrapper' => 'col-md-4', 'error' => '','hint' => '',],],'
options' => [ 'class' => 'form-horizontal', 'enctype' => 'multipart/form-data', ], ]);?>
<?php echo $form->field($mediamodel, 'title[]')->widget(FileInput::classname(), ['options'=>['multiple' => true]]);
Html::submitButton($model->isNewRecord ? 'Add' : 'Update');
use
$mediamodel->save (false);
instead of
$mediamodel->save ();
// You should handle errors like this.
if(!$mediamodel->save()){
// handle the errors of model.
var_dump($mediamodel->getErrors());
}
I'm using krajee DatePicker.
use yii\helpers\Html;
use yii\widgets\DetailView;
use yii\web\View;
use yii\data\ActiveDataProvider;
use kartik\widgets\DatePicker;
use yii\web\JsExpression;
echo DatePicker::widget([
'name' => 'dp',
'id' => 'dp',
'type' => DatePicker::TYPE_INLINE,
'value' => '',
'pluginOptions' => [
'startDate' => $model->fecha_inicio,
'format' => 'yyyy-mm-dd',
'beforeShowDay' => new \yii\web\JsExpression("function(date) {
startDate = new Date('".$model->fecha_inicio."');
endDate = new Date('".$model->fecha_fin."');
between=startDate<=date && endDate>=date;
console.log(date+' '+ (between));
dateFormat = date.getUTCFullYear() + '-' + ('0'+(date.getUTCMonth()+1)).slice(-2) + '-' + ('0'+date.getUTCDate()).slice(-2);
if (dateFormat == '".$model->fecha_inicio."') {
return {classes: 'start-date', tooltip: 'Title'};
}
if (dateFormat == '".$model->fecha_fin."') {
return {classes: 'end-date', tooltip: 'Title'};
}
if (between) {
return {classes: 'in-range available'}; //create a custom class in css with back color you want
}
return false;
}"),
],
'options' => [
// you can hide the input by setting the following
'class' => 'hide'
]
]);
Is there any way to render the DateRangePicker without it being able to recieve user input? (eg. no hover, no date selection). I want to render it on a webpage just to inform the user of a range, but the fact that the user can interact with it feels awkward in this scenario.
You can try to add "readonly" to the options. Just like this:
'options' => [
// you can hide the input by setting the following
'class' => 'hide',
'readonly' => 'readonly'
]
Try to use in your options array attribute disabled. SO it would be
'options' => [
'disabled' => 'true',
'class' => 'hide'
]
Well, this helped me do the trick, based on this answer.
Basically, I ended up using a wrapping div with the style:
<div style="pointer-events:none;"> ... </div>
This solved it easily and directly, and it seems to have decent cross-browser support.
<?php
echo '<div class="well well-sm" style="background-color: #fff; width:245px; pointer-events:none;">';
$date = new \DateTime($model->fecha_inicio);
$days = Proceso::calcularDias ($model->fecha_inicio,$model->fecha_fin);
echo DatePicker::widget([
'name' => 'dp',
'id' => 'dp',
'type' => DatePicker::TYPE_INLINE,
'value' => '',
'pluginOptions' => [
'defaultViewDate' => ([
'year'=>(int)$date->format('Y'),
'month'=>$date->format('m')-1,
'day'=>(int)$date->format('d')
]),
'format' => 'yyyy-mm-dd',
'beforeShowDay' => new JsExpression("function(date) {
startDate = new Date('".$model->fecha_inicio."');
endDate = new Date('".$model->fecha_fin."');
between=startDate<=date && endDate>=date;
dateFormat = date.getUTCFullYear() + '-' + ('0'+(date.getUTCMonth()+1)).slice(-2) + '-' + ('0'+date.getUTCDate()).slice(-2);
if (dateFormat == '".$model->fecha_inicio."') {
return {classes: 'start-date', tooltip: 'Title'};
}
if (dateFormat == '".$model->fecha_fin."') {
return {classes: 'end-date', tooltip: 'Title'};
}
if (between) {
return {classes: 'in-range available'}; //create a custom class in css with back color you want
}
return false;
}"),
],
'pluginEvents'=>[
],
'options' => [
'disabled' => 'true',
// you can hide the input by setting the following
'class' => 'hide'
]
]);
echo '</div>';
?>