Yii 2 No Refresh on SideNav Click - php

I have a SideNav in my bizadmin.php view:
<div class="row">
<div class="col-xs-3" id="sidenav">
<?php
echo SideNav::widget([
'type' => 'default',
'encodeLabels' => false,
//'heading' => $heading,
'items' => [
['label' => 'Add Staff', 'icon' => 'user', 'url' => ['/user/index']],
['label' => 'Store Configuration', 'icon' => 'cog', 'url' => ['/store/index']],
['label' => 'Add Transaction', 'icon' => 'duplicate', 'url' => ['/transaction/index']],
['label' => 'Add Account', 'icon' => 'book', 'url' => ['/account/index']],
],
]);
?>
</div>
<div class="col-xs-7">
<h2 id="bizstorename">Store Name</h2>
<h5>This is a store description. You can put anything here as long as it describes your store.</h5>
</div>
</div>
It looks like this:
Is there a way that when I click an item on my SideNav, it will NOT redirect to another page, but instead, a page will just be loaded inside a div (for example, in my case, inside <div class="col-xs-7">) beside the SideNav without refreshing the entire page.
I think I need to use jQuery or Ajax of some sort but I don't know how. Please let me know your thoughts.

Use jQuery's .load method to fetch a page and then append to #result:
$script = "
$('#sidenav ul li a').on('click', function(e) {
e.preventDefault();
var url = $(this).attr('href');
$('#result').load(url);
});
";
$this->registerJs($script, $this::POS_READY);
See jQuery's docs for more info.

Related

CakePHP 4 FormProtector instance has not been created error

I am currently in the process of updating a (rather big) application from CakePHP 3 to 4.
I have this template:
<?= $this->Form->create(
$dmpLayer,
[
'url' => [
'controller' => 'DmpLayers',
'action' => 'edit',
],
]
); ?>
<div class="row">
<div class="col-4">
<?= $this->element('DataLayers/layer-table'); ?>
</div>
<div id="form-div" class="col-6">
<div class="layer-form">
<?= $this->element('DataLayers/form') ?>
</div>
</div>
<div class="col-2">
<div class="layer-form">
<h2>Form Actions</h2>
<?= $this->Form->submit('Create/Update Layer', ['class' => 'btn btn-success']); ?>
</div>
</div>
</div>
<?= $this->Form->end(); ?>
<?= $this->Html->script('data-layers'); ?>
which includes the DataLayers/form element:
<div class="row">
<div class="col-12">
<h4>Artist Layer</h4>
<?php
echo $this->Html->tag('fieldset', $this->element(
'actions/add',
[
'url' => [
'prefix' => 'Admin',
'plugin' => false,
'controller' => 'SegmentCores',
'action' => 'add',
],
]
)
. $this->Form->control('artist_layer.segment_cores[]', [
'multiple',
'options' => $segmentCores,
'label' => 'Segment Core',
'value' => $selectedValues['segment_cores'],
])
. $this->Form->control('artist_layer.segment_potentials[]', [
'multiple',
'options' => $segmentPotentials,
'label' => 'Segment Potential',
'value' => $selectedValues['segment_potentials'],
])
. $this->Form->control('artist_layer.layer_tags[]', [
'multiple',
'options' => $layerTags,
'label' => 'Artist Tag',
'value' => $selectedValues['artist_tags'],
])
. $this->Form->control('artist_layer.genres[]', [
'empty' => 'No genre set',
'options' => $genres,
'label' => 'Genre',
'value' => $selectedValues['genres'],
]);
?>
</div>
</div>
<?php
$this->Form->unlockField('artist_layer.genres');
$this->Form->unlockField('artist_layer.segment_cores');
$this->Form->unlockField('artist_layer.segment_potentials');
$this->Form->unlockField('artist_layer.layer_tags');
?>
In the initialize function of the AppController I have this:
$this->loadComponent('Security');
When I visit the page, it doesn't render and I immediately get this error:
FormProtector instance has not been created. Ensure you have loaded the FormProtectionComponent in your controller and called FormHelper::create() before calling FormHelper::unlockField()
This is the only form in my application for which this error happens. Every other form is working fine, and I am calling the Form->unlockField() function in many of them.
I am obviously calling Form->create() in my code, so is this because I am including an element to add fields to the form that is defined in the "main" template? Or is there some other explanation?
I have already attempted adding
$this->loadComponent('FormProtection');
to my AppController, but this causes a whole lot more problems in many other places in the app, and it doesn't solve the problem anyway (the page renders, but I get an error when submitting the form to save the data).

How to prevent submit by double click

I created signup form using with ActiveForm in yii2, by double click, form submits, it submits automaticaly. How do I prevent it, I want form submit just by click on submit button.
why this happens and what's the solution?
This is my form code:
$form = ActiveForm::begin([
'enableAjaxValidation' => true,
]);
?>
<?=$form->field($model, 'nickname', ['addon' => ['prepend' => ['content' => '<i class="glyphicon glyphicon-option-horizontal"></i>']]])->label(false)->textInput()?>
<?=$form->field($model, 'phone_number', ['addon' => ['prepend' => ['content' => '<i class="glyphicon glyphicon-option-horizontal"></i>']]])->label(false)->textInput()?>
<?=$form->field($model, 'email', ['addon' => ['prepend' => ['content' => '#']]])->label(false)->textInput()?>
<?=$form->field($model, 'password', [
'addon' => ['prepend' => ['content' => '<i class="fa fa-key"></i>']]])->passwordInput(['autocomplete' => 'off'])->label(false)->passwordInput();
?>
<div class="form-group">
<?=Html::submitButton(Yii::t('app', 'Signup'), ['value' => 'signupp', 'class' => 'btn btn-primary', 'name' => 'signupButton', 'style' => 'width:100%;'])?>
</div>
<?php ActiveForm::end();?>
You can use the ActiveForm's js event beforeSubmit to disable the button at the time the form is submitted, you can use CSS pointerEvents:'none' to disable the click on the button.
Assing an id="my-form" to your form and id="my-submit" to your submit button and use the below script on top of your view and your button will be disabled at the time of submission.
$js =<<< JS
$("#my-form").on("beforeSubmit",function(e){
e.preventDefault();
$("#my-submit").css({pointerEvents:'none'});
return true;
});
JS;
$this->registerJs($js, \yii\web\View::POS_READY);

Get selected rows value from kartik gridView in modal and pass it to parent form

I try to get value from modal bootstrap (contain table kartik gridview), and i want to pass the selected value to parent form (action create form). How to do that? Please advice.
modal form contains fields like this
<?php
$gridColumns = [
'id',
'date',
[
'attribute' => 'agen_id',
'value' => 'agen.agen_name'
],
[
'attribute' => 'price',
'format' => ['decimal', 0],
],
'remark_1:ntext',
'remark_2:ntext',
] ?>
and this is the button in parent form
<div class="col-xs-8">
<div class="form-group field-poagen-price">
<br>
<?= Html::button('Price List', ['value' => Url::to('../pricelist/list'), 'class' => 'btn btn-primary', 'id' => 'BtnModalPriceList']) ?>
<?php
Modal::begin([
'header' => 'List Harga',
'id' => 'modal',
'size' => 'modal-md'
]);
echo "<div id='modalContent'></div>";
Modal::end();
?>
</div>
</div>
and i register my jquery like this
$('#BtnModalPriceList').click(function(){
$('#modal').modal('show')
.find('#modalContent')
.load($(this).attr('value'));});
I want to get the value from modal to pass to the parent in order to fill the required field.
I have searched for a few days and still have no luck.
Please advice for the master. Thanks before.
I have solved it. This is what i do.
Create custom button in the gridView
[
'class' => 'yii\grid\ActionColumn',
'template' => '{select}',
'buttons' => [
'select' => function($url, $model, $key){
return Html::button('Select', [
'title' => Yii::t('yii', 'Select'),
'aria-label' => Yii::t('yii', 'Select'),
'class' => 'btn btn-primary select-row',
'data-id' => $model->id,
]);
},
],
],
and then register to jquery to process the data
$(document).on('click', '.select-row', function(){
// get id from custom button
var id = $(this).attr('data-id');
$.get('../pricelist/get-price', {id : id}, function(data){
$('#poagen-price').val(data);
});
$('#modalPriceList').modal('hide');
$('#poagen-fee').focus();
});
got help from #milos-ozegovic

Yii2 Pjax reloads entire page on second form submit

I cannot seem to figure out why pjax reloads the page on the second form submission. It works exactly as intended on the first form submission pulling from this url /site/profile?UserSearch%5Bsearchstring%5D=mi&_pjax=%23form-pjax, however, after that first one it loses the ending of the url /site/profile?UserSearch%5Bsearchstring%5D=m. I checked the actual html code and the form is retaining the data-ajax attribute. I tried increasing the timeout as had been suggested when pjax is reloading the entire page, but that did not change anything.
Below is the code from my view
<?php Pjax::begin(['timeout' => 5000, 'id' => 'form-pjax']); ?>
<?php $form = ActiveForm::begin([
'method' => 'get',
'action' => Url::to(['site/profile']),
'options' => ['data-pjax' => true ],
]); ?>
<?= $form->field($searchModel, 'searchstring', [
'template' => '<div class="input-group">{input}<span class="input-group-btn">' .
Html::submitButton('Search', ['class' => 'btn btn-default']) .
'</span></div>',
])->textInput(['placeholder' => 'Find friends by username or email']);
?>
<?php ActiveForm::end(); ?>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
'username',
[
'label' => 'View Profile',
'format' => 'raw',
'value'=>function ($data) {
return Html::a(Html::encode("View Profile"),'/site/redirectprofile/'.$data->id);
},
],
[
'label' => 'Follow',
'format' => 'raw',
'value'=>function ($data) {
return Html::a(Html::encode(Follow::find()->where(['user_id' => $data->id, 'follower_id' => Yii::$app->user->Id])->exists() ? 'Unfollow' : 'Follow'),'/site/follow/'.$data->id.'/'.$data->username);
},
],
],
'summary'=>'',
]); ?>
<?php Pjax::end(); ?>
You must call needed javascript triggers/functions after every pjax reload like:
$('#form-pjax').on('pjax:success', function() {
/*call Your functions here, or copy from your generated page js code,
that bind event to pjax form,
at end of generated html You should have something like: */
jQuery(document).on('submit', "#form-pjax form[data-pjax]", function (event) {
jQuery.pjax.submit(event, '#form-pjax', {"push":true,"replace":false,"timeout":000,"scrollTo":false});
});
});
This is not yii2 issue, it's how javascript works, when You add dynamically content it's needed to bind triggers/events for every added element.

Passing data from gridview button to modal window

I am trying to pass data from a button within a gridview to a modal window. I need to pass the ID of the record in order to be able to reference it after submitting the form within the modal window.
I am struggling with this quite a bit. First I need to be able to pass the ID variable to the modal, and then upon clicking the submit button make an ajax call to create a new record within the DB.
The Gridview
if(isset($results)){
$this->widget('bootstrap.widgets.TbExtendedGridView', array(
'id'=>'searchgrid',
'fixedHeader' => true,
'headerOffset' => 40, // 40px is the height of the main navigation at bootstrap
'type'=>'condensed',
'dataProvider'=>$results,
'responsiveTable' => true,
'template'=>"{items}",
'columns'=>array(
array('name'=>'title', 'header'=>'Name'),
array('name'=>'city', 'header'=>'City'),
array('name'=>'state', 'header'=>'State'),
array('name'=>'leads', 'header'=>'Leads', 'value'=>'Parkslist::model()->leadRange($data["leads"])'),
array('name'=>'pastbid', 'header'=>'Previous', 'value'=>'Parkslist::model()->pastBid($data["pasthighbid"])'),
array('name'=>'currentbid', 'header'=>'Current', 'value'=>'Parkslist::model()->highBid($data["currenthighbid"], $data["secondhighbid"], $data["countcurrenthighbid"])'),
array('name'=>'minimumbid', 'header'=>'Minimum', 'value'=>'Parkslist::model()->minimumBid($data["currenthighbid"], $data["secondhighbid"], $data["countcurrenthighbid"])'),
array('name'=>'userhighbid', 'header'=>'Your Bid'),
array('name'=>'placebid', 'header'=>'Bid', 'value'=>'CHtml::textField("bid" . $data["id"])', 'type'=>'raw'),
array('name'=>'report', 'header'=>'Report',
'value'=>function($data){
$this->widget('bootstrap.widgets.TbButton', array(
'label' => 'Click me',
'type' => 'primary',
'htmlOptions' => array(
'data-toggle' => 'modal',
'data-target' => '#myModal',
'data-id' => '$data["id"]',
),
));
}
),
),
));
}
The Modal
<?php
$this->beginWidget('bootstrap.widgets.TbModal', array('id' => 'myModal')); ?>
<div class="modal-header">
<a class="close" data-dismiss="modal">×</a>
<h4>Why should this park be removed?</h4>
</div>
<form>
<div class="modal-body">
<select>
<option>Duplicate</option>
<option>Closed</option>
</select>
</div>
<div class="modal-footer">
<?php $this->widget('bootstrap.widgets.TbButton', array(
'type' => 'primary',
'buttonType'=>'submit',
'label' => 'Save changes',
'url' => '#',
'htmlOptions' => array('data-dismiss' => 'modal'),
)); ?>
<?php $this->widget('bootstrap.widgets.TbButton', array(
'label' => 'Close',
'url' => '#',
'htmlOptions' => array('data-dismiss' => 'modal'),
)); ?>
</div>
</form>
<?php $this->endWidget(); ?>
I was able to get this working. I would assume there might be a better solution but this seems to work.
First, inside of the button in the gridview I made the button ID = to the id of the record. Next, I created a javascript function called includeData and included the button ID.
Button Code
array('name'=>'report', 'header'=>'Report',
'value'=>function($data){
$this->widget('bootstrap.widgets.TbButton', array(
'label' => 'Click me',
'type' => 'primary',
'htmlOptions' => array(
'id'=>$data["id"],
'data-toggle' => 'modal',
'data-target' => '#myModal',
'data-id' => '$data["id"]',
'onClick' => 'includeData(this.id);'
),
));
}
),
JS Code
<script type='text/javascript'>
function includeData(parkid){
$('#reportparkid').val(parkid);
}
</script>
The JS function just sets the value of a hidden field equal to the buttonid. I would love to see some better ways to handle this.
Thanks

Categories