Yii2: Show field/checkbox after checkbox is selected - checkbox

I have an ActiveForm in my _form view:
<?php $form = ActiveForm::begin(); ?> <?= $form->field($model, 'isInternal')->checkbox() ?> <?php ActiveForm::end(); ?>
('isInternal' is a boolean)
If the checkbox is selected I want to show another checkbox:
$form->field($model, 'activateReminder')->checkbox();
Is there a possibility? Maybe with JavaScript like this?
<?= $form->field($model, 'isInternal')->checkbox(['onclick' =>
'showInternDetails()']) ?>
<script>
function showInternDetails() {
$model->isInternal = 1;
}
</script>
<?php
if($model->isInternal == true)
{
$form->field($model, 'activateReminder')->checkbox();
}
?>

You can do that by JS:
<?php
$this->registerJs(
"$('#myBox').on('change', function() { if($(this).is(":checked")){// Display your input...}else {// hide it} });",
View::POS_READY
);

You can use the when and whenClient options inside the model rules that you have declared so that it works when creating or updating both on the model end to require and show error to the user that he needs to select the value for the check-box and also to show and hide the activateReminder at the same time.
So go inside the model that you are using with this form and add a rule like below.
public function rules(){
return [
[['activateReminder'],'required','when'=>function($model){return ($model->isInternal);},
'whenClient'=>'function(attribute,value){
if($("#'.\yii\helpers\Html::getInputId($this, 'isInternal').'").val()===1){
$("#'.\yii\helpers\Html::getInputId($this, 'activateReminder').'").show();
return true;
}else{
$("#'.\yii\helpers\Html::getInputId($this, 'activateReminder').'").hide();
}
}']
];
}

Thank you for your answers!!
I have solved it as follows:
function isInternalOnClick(){
$('#isInternalCheckbox').on('change',function(){ showOrHideActivateReminder();});
}
function showOrHideActivateReminder() {
if($('#isInternalCheckbox').is(':checked'))
{
$('#hiddenActivateReminder').show()
}
else{
$('#hiddenActivateReminder').hide();
}
}
$(document).ready(function() {
<?php
if($model->isInternal)
{
echo "
showOrHideActivateReminder();
";
}
?>
});

Related

Display header and footer using CakePdf

I'm trying to render a pdf using CakePdf 3.5.3 using the wkhtmltopdf engine with html headers on every page showing custom text as well as the page number.
https://wkhtmltopdf.org/usage/wkhtmltopdf.txt describes the process as passing the --header-html command line argument and using the following javascript and html:
<!DOCTYPE html>
<html><head><script>
function subst() {
var vars = {};
var query_strings_from_url = document.location.search.substring(1).split('&');
for (var query_string in query_strings_from_url) {
if (query_strings_from_url.hasOwnProperty(query_string)) {
var temp_var = query_strings_from_url[query_string].split('=', 2);
vars[temp_var[0]] = decodeURI(temp_var[1]);
}
}
var css_selector_classes = ['page', 'frompage', 'topage', 'webpage', 'section', 'subsection', 'date', 'isodate', 'time', 'title', 'doctitle', 'sitepage', 'sitepages'];
for (var css_class in css_selector_classes) {
if (css_selector_classes.hasOwnProperty(css_class)) {
var element = document.getElementsByClassName(css_selector_classes[css_class]);
for (var j = 0; j < element.length; ++j) {
element[j].textContent = vars[css_selector_classes[css_class]];
}
}
}
}
</script></head><body style="border:0; margin: 0;" onload="subst()">
<table style="border-bottom: 1px solid black; width: 100%">
<tr>
<td class="section"></td>
<td style="text-align:right">
Page <span class="page"></span> of <span class="topage"></span>
</td>
</tr>
</table>
</body></html>
I created src/Template/Layout/pdf/default.ctp and src/Template/Layout/pdf/header.ctp
default.ctp
<!DOCTYPE html>
<html lang="en">
<head>
<?= $this->Html->charset() ?>
<title>
<?= $this->fetch('title') ?>
</title>
<?= $this->Html->meta('icon') ?>
</head>
<body>
<?= $this->Flash->render() ?>
<div>
<?= $this->fetch('content') ?>
</div>
</body>
</html>
header.ctp
<!DOCTYPE html>
<html lang="en">
<head>
<script>
function subst() {
var vars = {};
var query_strings_from_url = document.location.search.substring(1).split('&');
for (var query_string in query_strings_from_url) {
if (query_strings_from_url.hasOwnProperty(query_string)) {
var temp_var = query_strings_from_url[query_string].split('=', 2);
vars[temp_var[0]] = decodeURI(temp_var[1]);
}
}
var css_selector_classes = ['page', 'frompage', 'topage', 'webpage', 'section', 'subsection', 'date', 'isodate', 'time', 'title', 'doctitle', 'sitepage', 'sitepages'];
for (var css_class in css_selector_classes) {
if (css_selector_classes.hasOwnProperty(css_class)) {
var element = document.getElementsByClassName(css_selector_classes[css_class]);
for (var j = 0; j < element.length; ++j) {
element[j].textContent = vars[css_selector_classes[css_class]];
}
}
}
}
</script>
<title></title>
</head>
<body onload="subst()">
<?= $some_view_variable ?>
Page <span class="page"></span> of <span class="topage"></span>
</body>
</html>
This is how I configure CakePdf in my controller.
Configure::write('CakePdf', [
'engine' => [
'className' => 'CakePdf.WkHtmlToPdf',
'binary' => "/usr/local/bin/wkhtmltopdf",
'options' => [
'header-html' => APP . 'Template' . DS . 'Layout' . DS . 'pdf' . DS . 'header.ctp',
],
],
'margin' => [
'bottom' => 0,
'left' => 0,
'right' => 0,
'top' => 0
],
'pageSize' => 'Letter',
'orientation' => 'portrait'
]);
The header information is not shown in the generated PDF. I'm also not sure how to pass viewVars to the header template.
My understanding is that the header must be in a .html file, it must be raw HTML (e.g. not a Cake template), and I've not found a way to specify the header-html option. Here's the hack I've used to work around it:
$view = new View();
$dir = TMP . 'html';
if (!is_dir($dir)) {
mkdir($dir);
}
while (true) {
// WkHtmlToPdf requires .html extension on these files, but tempnam can't do that.
$file = tempnam($dir, 'header');
if (rename($file, $file . '.html')) {
$file .= '.html';
break;
} else {
unlink($file);
}
}
file_put_contents($file, '<!DOCTYPE HTML><html lang=\'en-US\'><body style=\'font-family: "Times New Roman"\'>' . $view->element($element) . '</body></html>');
// Hack to access protected member: we want --header-html on the command line.
// This is easier than extending the class for a single such usage.
$closure = function($file) {
$this->_header = ['html' => 'file://' . $file];
};
$hack = \Closure::bind($closure, $pdf, 'CakePdf\Pdf\CakePdf');
$hack($file);
$this->_tmp[] = $file;
This is, of course, all off in a separate function, so it's easy to replace if I find a better way. :-)

Why do AJAX requests trigger a 400 response despite unlocking the actions with the security component?

I'm trying to get an ajax request working in CakePHP4, but keep running into the CSRF protection.
In my controller:
public function beforeFilter(EventInterface $event)
{
parent::beforeFilter($event);
$this->Security->setConfig('unlockedActions', ['players']);
}
public function players()
{
$players = ['Sjaak Afhaak', 'Aad Kippezaad', 'Gras Kaffer', 'Tedje van Es'];
if ($this->request->is('ajax')) {
$this->response = $this->response->withDisabledCache();
}
$letter = trim($this->request->getData('letter'));
if (!empty($letter)) {
$players = array_filter($spelers, function ($haystack) use ($letter) {
return(strpos($haystack, $letter));
});
}
$this->set(compact('players'));
$this->viewBuilder()->setOption('serialize', ['players']);
$this->RequestHandler->renderAs($this, 'json');
}
Then in the template file:
<?php echo $this->Html->script('jquery.min'); ?>
<div class="container">
<div class="row">
<div class="column">
<div class="users form content">
<?php echo $this->Form->create(null, ['url' => \Cake\Routing\Router::pathUrl('Ado::players')]); ?>
<fieldset>
<legend>Players</legend>
<?php echo $this->Form->text('letter', ['placeholder' => 'Begin letter(s)']); ?>
</fieldset>
<?= $this->Form->button('OK'); ?>
<?= $this->Form->end() ?>
</div>
</div>
<div class="column response">
...
</div>
</div>
</div>
<script>
$(document).ready(function () {
$(document).on("submit", "form", function (event) {
var $form = $(this);
var $target = $('div.response');
var csrf = $('input[name=_csrfToken]', $form).val();
var data = { letter: $('input[name=letter]', $form).val() };
$target.html('');
$.ajax({
method: "POST",
url: $form.attr('action'),
beforeSend: function(xhr) {
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('X-CSRF-Token', csrf);
},
data: data,
dataType: "json"
})
.done(function (response) {
var items = [];
$.each( response, function( key, val ) {
items.push( "<li id='" + key + "'>" + val + "</li>" );
});
$( "<ul/>", {
"class": "spelers-list",
html: items.join( "" )
}).appendTo( $target );
});
event.preventDefault();
});
});
</script>
Without the beforeSend in the ajax call, i get a 403 response.
If i include the X-CSRF-Token i receive a 400 response.
2020-06-18 09:49:38 Error: [Cake\Http\Exception\BadRequestException] `_Token` was not found in request data. in src\vendor\cakephp\cakephp\src\Controller\Component\FormProtectionComponent.php on line 143
Stack Trace:
- src\vendor\cakephp\cakephp\src\Controller\Component\FormProtectionComponent.php:97
- src\vendor\cakephp\cakephp\src\Event\EventManager.php:309
- src\vendor\cakephp\cakephp\src\Event\EventManager.php:286
- src\vendor\cakephp\cakephp\src\Event\EventDispatcherTrait.php:92
- src\vendor\cakephp\cakephp\src\Controller\Controller.php:569
- src\vendor\cakephp\cakephp\src\Controller\ControllerFactory.php:72
- src\vendor\cakephp\cakephp\src\Http\BaseApplication.php:229
- src\vendor\cakephp\cakephp\src\Http\Runner.php:77
- src\vendor\cakephp\cakephp\src\Http\Middleware\BodyParserMiddleware.php:164
- src\vendor\cakephp\cakephp\src\Http\Runner.php:73
- src\vendor\cakephp\authorization\src\Middleware\AuthorizationMiddleware.php:129
- src\vendor\cakephp\cakephp\src\Http\Runner.php:73
- src\vendor\cakephp\authentication\src\Middleware\AuthenticationMiddleware.php:124
- src\vendor\cakephp\cakephp\src\Http\Runner.php:73
- src\vendor\cakephp\cakephp\src\Http\Runner.php:77
- src\vendor\cakephp\cakephp\src\Http\Middleware\CsrfProtectionMiddleware.php:138
- src\vendor\cakephp\cakephp\src\Http\Runner.php:73
- src\vendor\cakephp\cakephp\src\Http\Runner.php:58
- src\vendor\cakephp\cakephp\src\Routing\Middleware\RoutingMiddleware.php:166
- src\vendor\cakephp\cakephp\src\Http\Runner.php:73
- src\vendor\cakephp\cakephp\src\Routing\Middleware\AssetMiddleware.php:68
- src\vendor\cakephp\cakephp\src\Http\Runner.php:73
- src\vendor\cakephp\cakephp\src\Error\Middleware\ErrorHandlerMiddleware.php:119
- src\vendor\cakephp\cakephp\src\Http\Runner.php:73
- src\vendor\cakephp\debug_kit\src\Middleware\DebugKitMiddleware.php:60
- src\vendor\cakephp\cakephp\src\Http\Runner.php:73
- src\vendor\cakephp\cakephp\src\Http\Runner.php:58
- src\vendor\cakephp\cakephp\src\Http\Server.php:90
- src\webroot\index.php:41
Not sure if it's related, but i'm using the Authentication plugin. (https://book.cakephp.org/authentication/2/en/index.html)
As can be seen in the stacktrace, the error stems from the form protection component, not the security component, so unlocking actions on the security component won't do anything.
The security component is deprecated (the Cookbook doesn't seem to mention that), and the form protection component is one of the utilities that are ment to replace it (others are the CSRF middleware and the HTTPS enforcer middleware) - you shouldn't use both, drop the security component (and by that I mean to also remove the related loadComponent() call), and configure the form protection component accordingly instead!
$this->FormProtection->setConfig('unlockedActions', ['players']);
The docs really need some overhaul here, not only is there no deprecation notice for the security component, but also the form protection component isn't listed in the components section.

Insert array using codeigniter

I try to insert multiple arrays into database using codeigniter and ajax. After click the submit, database insert to mysql but all the value is blank. What did I miss?
My view:
<input type="hidden" name="iduser[]" id="iduser[]" value="<?php echo $rowmyuser->iduser; ?>"/>
<input type="hidden" name="idproduk[]" id="idproduk[]" value="<?php echo $rowproduk->idproduct; ?>"/>
<input type="text" class="form-control input-sm" name="settarget[]" id="settarget[]"/>
Save
My controller:
public function inserttarget()
{
$this->target_m->inserttarget_m();
}
My model:
function inserttarget_m() {
$iduser = $this->input->post("iduser");
$idproduk = $this->input->post("idproduk");
$settarget = $this->input->post("settarget");
$temp = count($this->input->post("iduser"));
$datatarget = array();
for($i=0; $i < 3; $i++)
{
$datatarget[]=array(
"iduser"=>$iduser[$i],
"idproduct"=>$idproduk[$i],
"target"=>$settarget[$i],
);
}
$this->db->insert_batch("tbl_targetsales",$datatarget);
}
The Ajax code:
function insert_target()
{
var DataString=$("#frm_target").serialize();
document.getElementById("save_target").innerHTML = "<i class='fa fa-cog fa-spin fa-lg fa-fw'></i> Saving...";
$.ajax({
type: 'POST',
url: '<?php echo base_url();?>target/inserttarget',
data: DataString,
success: function (data) {
//jQuery("#attendence_report_holder").html(response);
swal({
text: 'success'
});
$("#frm_target")[0].reset();
document.getElementById("save_target").innerHTML = "<i class='fa fa-save'> </i>Save";
window.location='<?php echo base_url(); ?>target';
},
error:function(data){
swal({
text: 'error',
});
document.getElementById("save_target").innerHTML = "<i class='fa fa-save'> </i>Save";
}
});
}
I need advice please, what is the problem in the code. Thanks in advance
first you call wrong the inputs in your html for the inputs name are
iduser[]
idproduk[]
settarget[]
and in your model you call with, and in the array you make to insert you call different variables that you save it
iduser
idproduct
target
replace all you madel with (using the correct names from form and variables names)
function inserttarget_m() {
$iduser = $this->input->post("iduser");
$idproduct = $this->input->post("idproduk");
$target = $this->input->post("settarget");
$temp = count($iduser);
$datatarget = array();
for($i=0; $i < $temp; $i++){
$datatarget[] = array(
"iduser" => $iduser[$i],
"idproduct" => $idproduct[$i],
"target" => $target[$i],
);
}
$this->db->insert_batch("tbl_targetsales", $datatarget);
}

Yii2: save checkbox false as NULL

In Yii2 I have ActiveForm with checkbox field. In mysql database it is tinyint(1) column that can be NULL.
I need unchecked checkbox (false value) to be saved as NULL in database. Currently when checkbox is unchecked, it is saved as (int) 0.
What is the proper way to save false value as NULL?
Here is the model:
class ProductToProductCategory extends ActiveRecord {
public function rules()
{
return [
['product_category_id', 'required'],
['product_category_id', 'integer'],
['is_main', 'boolean'],
];
}
}
Here is the view:
<?= $form->field($model, "is_main")->checkbox() ?>
public function rules()
{
return [
['product_category_id', 'required'],
['product_category_id', 'integer'],
['is_main', 'boolean'],
['is_main', 'filter', function ($value) {
// return value you need
return $value ?: null;
}, 'skipOnError' => true],
];
}
Never tried it but you should be able to do it implementing the beforeSave method of the saved model.
public function beforeSave($insert)
{
if (!parent::beforeSave($insert)) {
return false;
}
if( $this->scenario == "strangeNullScenario" ) {
if( empty( $this->FIELD ) ) {
$this->FIELD = null;
}
}
return true;
}
Just pass uncheck option
<?= $form->field($model, "is_main")->checkbox(['uncheck' => null]) ?>

Edit Comment vai modal dialog box doesn't work correctly

<?php
echo $this->Form->postLink(
'',
array('action' => 'edit',$comment['id'],
'controller'=>'Comments',
),array('class'=>'glyphicon glyphicon-edit','onClick'=>'showDialog()') )?>
This is comment edit icon that I create when I click the Icon the
model dialog box is pop up .
<div id="overlay" onClick="hideDialog()"></div>
<div id="dialog">
<h2>Edit Comment <span onClick="hideDialog()">×</span></h2>
<?php echo $this->Form->create('Comment',array('enctype'=>'multipart/form-data'));?>
<?php echo $this->Form->input('Comment.comment',array('class'=>'form-control'));
echo $this->Form->end('Save');
?>
</div>
<script>
function showDialog() {
document.getElementById("overlay").style.display = "block";
document.getElementById("dialog").style.display = "block";
}
function hideDialog() {
document.getElementById("overlay").style.display = "none";
document.getElementById("dialog").style.display = "none";
}
</script>
The dialog to edit the comment but The comment just add as a another
comment but not edit . Why? Here is the Edit Function in my controller
public function edit($id = null) {
$user_id=$this->Auth->user('id');
$comment_fields=$this->Comment->findById($id);
$comment_id=$comment_fields['Comment']['id'];
$comment = $this->Comment->findById($id);
if (!($user_id == $comment_fields['Comment']['user_id'])) {
$this->Flash->error(__('Unable to edit your post.'));
return $this->redirect(array('action'=>'../posts/view',$comment_fields['Comment']['foreign_id']));
}
if (!$comment)
{
$this->redirect(array('action'=>'../posts/view',$comment_fields['Comment']['foreign_id']));
}
if ($this->request->is(array('post', 'put'))) {
if($this->Comment->id = $id)
{
if ($this->Comment->save($this->request->data)) {
$this->Flash->success(__('Your Comment has been updated.'));
$this->redirect(array('action'=>'../posts/view',$comment_fields['Comment']['foreign_id']));
}
}else{
$this->Flash->error(__('Unable to update your Comment.'));
}
}
if (!$this->request->data) {
$this->request->data = $comment;
}
}
You are trying to assign a value in the if's conditional statement part!
if($this->Comment->id = $id) : This is wrong because that part is for checking conditions.
The solution to your problem would be:
$this->Comment->id = $id;
if ($this->Comment->exists()) {
if ($this->Comment->save($this->request->data)) {
$this->Flash->success(__('Your Comment has been updated.'));
$this>redirect(array('action'=>'../posts/view',$comment_fields['Comment']['foreign_id']));
}
}
else {
$this->Flash->error(__('Unable to update your Comment.'));
}

Resources