TYPO3: Use t3lib_TCEforms in frontend plugin - forms

I would like to use as much standard TYPO3 as possible to create a form to edit single records from tx_mytable.
In pi1 i load the tca for the table:
t3lib_div::loadTCA('tx_mytable');
Now I would like to use standard functions to create my form elements more or less like it is done in the backend...
I found this for the front end but cannot find any working examples:
t3lib_TCEforms_fe.php (that extends the normal t3lib_TCEforms)
Is this the right way to go or is there a better way?

I got something working but not really that nice code in the frontend
Here is a link that telss that TCA is not enough but two new entries in the array is needed
http://www.martin-helmich.de/?p=15
It is itemFormElName and itemFormElValue
// include tceforms_fe (place outside class where pipase is included)
require_once(PATH_t3lib.'class.t3lib_tceforms_fe.php');
// load TCA for table in frontend
t3lib_div::loadTCA('tx_ogcrmdb_tasks');
// init tceforms
$this->tceforms = t3lib_div::makeInstance("t3lib_TCEforms_FE");
$this->tceforms->initDefaultBEMode(); // is needed ??
$this->tceforms->backPath = $GLOBALS['BACK_PATH']; // is empty... may not be needed
//////////REPEAT FOR EACH INPUT FIELD/////////
// start create input fields, here just a single select for responsible
// conf used for tceforms similar to but not exactly like normal TCA
$conftest = array(
'itemFormElName' => $GLOBALS['TCA']['tx_ogcrmdb_tasks']['columns']['responsible']['label'],
'itemFormElValue' => 1,
'fieldConf' => array(
'config' => $GLOBALS['TCA']['tx_ogcrmdb_tasks']['columns']['responsible']['config']
)
);
// create input field
$this->content .= $this->tceforms->getSingleField_SW('','',array(),$conftest);
// wrap in form
$output = '<form action="" name="editform" method="post">';
$output .= $this->content;
$output .= '</form>';
// wrap and return output
return $output;
Still looking for a working example with custem template for input fields.

Related

How to add a class to a postLink form - CakePHP 3.4

Is it possible to add a class to the hidden form created by CakePHP's postLink form helper?
Here's my code
Form->postLink(
' ' . __('Delete'),
['action' => 'delete', $this->fetch('item')],
['confirm' => __('Are you sure you want to delete # {0}?', $this->fetch('item'))
,'escape' => false
,'title' => __('Delete')
,'class' => 'btn btn-danger btn-xs isAction'
]) ?>
Note that I'm not looking to add a class to the link that gets created.
Any ideas are welcome!
There's pretty much only one way currently, and that would be to change the formStart template temporarily, something along the lines of this:
// read current template and set the new one
$formStart = $this->Form->getTemplates('formStart');
$this->Form->setTemplates([
'formStart' => '<form class="hiddenFormClass"{{attrs}}>'
]);
echo $this->Form->postLink(/* ... */);
// set the template back to its previous state
$this->Form->setTemplates([
'formStart' => $formStart
]);
It's also possible to reset the templates to their default state using the resetTemplates() method, however this would reset all possible changes made to any of the templates, so it's probably better to play it safe as shown above.
See also
Cookbook > Controllers > Views > Helpers > Form > Customizing the Templates FormHelper Uses
API \Cake\View\Helper\FormHelper::setTemplates()
API \Cake\View\Helper\FormHelper::getTemplates()
API \Cake\View\Helper\FormHelper::resetTemplates()

CSRF field is missing when I embed my form with a requestAction in CakePHP 3

I want to embed a contact form in multiple places on my website.
I developed a contact form in a contact() function within my MessagesController.php:
// MessagesController.php
public function contact()
{
$this->set('title', 'Contact');
$message = $this->Messages->newEntity();
... // shortened for brevity
$this->set(compact('message'));
$this->set('_serialize', ['message']);
}
I loaded the CSRF component in the initialize() function of the AppController.php:
// AppController.php
public function initialize()
{
parent::initialize();
$this->loadComponent('Csrf');
... // shortened for brevity
}
The form is rendered with a contact.ctp and it works fine.
I followed CakePHP's cookbook which suggests using requestAction() within an element, then echoing the element where I want it:
// contact_form.ctp
<?php
echo $this->requestAction(
['controller' => 'Messages', 'action' => 'contact']
);
?>
And:
// home.ctp
<?= $this->element('contact_form'); ?>
The problem is that the form is rendered fine, but the CSRF hidden field is missing. It should be automatically added to the form since the CSRF component is called in the AppController.php.
I guess either using an element with a requestAction() isn't the solution for this particular case, or I am doing something wrong.
Any ideas? Thanks in advance for the input!
Request parameters need to be passed manually
requestAction() uses a new \Cake\Network\Request instance, and it doesn't pass the _Token and _csrf parameters to it, so that's why things break.
While you could pass them yourself via the $extra argument, like
$this->requestAction(
['controller' => 'Messages', 'action' => 'contact'],
[
'_Token' => $this->request->param('_Token'),
'_csrf' => $this->request->param('_csrf')
]
);
Use a cell instead
I would suggest using a cell instead, which is way more lightweight than requesting an action, also it operates in the current request and thus will work with the CSRF component out of the box.
You'd pretty much just need to copy your controller action code (as far as the code is concerned that you are showing), and add a loadModel() call to load the Messages table, something like
src/View/Cell/ContactFormCell.php
namespace App\View\Cell;
use Cake\View\Cell;
class ContactFormCell extends Cell
{
public function display()
{
$this->loadModel('Messages');
$this->set('title', 'Contact');
$message = $this->Messages->newEntity();
// ... shortened for brevity
$this->set(compact('message'));
$this->set('_serialize', ['message']);
}
}
Create the form in the corresponding cell template
src/Template/Cell/ContactForm/display.ctp
<?php
echo $this->Form->create(
/* ... */,
// The URL needs to be set explicitly, as the form is being
// created in the context of the current request
['url' => ['controller' => 'Messages', 'action' => 'contact']]
);
// ...
And then wherever you want to place the form, just use <?= $this->cell('ContactForm') ?>.
See also
API > \Cake\Routing\RequestActionTrait::requestAction()
Cookbook > Views > Cells

Create Email HTML Using Partial in Zend Framework 2?

I'm working on a system where we want to queue up a batch of emails and then send them using a queue (so I can't use \Zend\Mail directly). The goal is to not have HTML inside the models that are creating the emails but instead have them in a view file. I'm trying to call the partial view helper inside the models (which I did in ZF1) but can't find anything on the web on how to do this. Is this possible in ZF2 or is there a better way? I've managed it before where we've had the HTML inside the models and it's been a mess. :-)
You can just create a template somewhere, pull the renderer from your service locator, and render away:
<?php
// this assumes you're in some AbstractActionController,
// but you could be in some service class that has the
// renderer injected, etc.
// template vars
$vars = array(/* .... */);
// create a ViewModel
$vm = new \Zend\View\Model\ViewModel($vars);
// path to your email template, compatible with your template map config.
$tpl = 'mymodule/emails/some-email-template.phtml';
$vm->setTemplate($tpl);
// get the renderer from the ServiceManager, so it's all nicely configured.
$renderer = $this->getServiceLocator()->get('Zend\View\Renderer\RendererInterface');
// render some HTML
$html = $renderer->render($vm);
You could do it this way:
1. In the module.config define those HTML mail content template views.
'view_manager' => array(
(...)
'template_map' => array(
'mail_content_1' => __DIR__ . '/../view/<MODULE_NAME>/mail_content_1.phtml',
),
(...)
)
2. Load the Template View in your model and get the HTML.
use Zend\View\Model\ViewModel;
public function getMailHTML() {
$view = new ViewModel;
$variables = array( "parm1" => "value1" );
//SET THE VARIABLES, LIKE IN PARTIALS
$view->setVariables( $variables );
//SET THE TEMPLATE VIEW KEY DEFINED IN THE module.config
$view->setTemplate( 'mail_content_1' );
//YOU'LL HAVE TO BE ABLE TO USE THE ServiceManager IN YOUR MAIL MODELS.
//RENDERING THE VIEW YOU'LL GET THE HTML
return $this->serviceManager->get( 'viewrenderer' )->render( $view );
}

Using HTML::FormFu, how do you change a field value *after* processing so that it appears modified in Template Toolkit?

For example, if I process a form:
my $form_input = { input_data => '123' };
$form->process($form_input);
Then I want to alter the value of 'input_data':
my $clearme = $form->get_field('input_data');
$clearme->value("546"); # doesn't seem to work
..Before pushing the form object to TT:
template 'index' => { form => $form }; # using Dancer
'input_data' seems to retain it's original value (123). Any hints on what I'm doing wrong, or what I should be doing?
Thanks
After looking at the documentation and doing some testing, I think you want
$form->add_valid(input_data => '546');

Add Database Row Button Cakephp

The Controller:
function add(){
if (!empty($this->data)) {
$qnote = $this->Qnote->save($this->data);
if (!empty($qnote)) {
$this->data['Step']['qnote_id'] = $this->Qnote->id;
$this->Qnote->Step->save($this->data);
}
$this->Session->setFlash('Your note has been saved.');
$this->redirect(array('action' => 'index'));
}
}
The Form.
<?php
$userID = Authsome::get('id');
echo $form->create('Qnote', array('action'=>'add'));
echo $form->input('Qnote.id', array('type' => 'hidden'));
echo $form->input('Qnote.user_id', array('value' => $userID, 'type' => 'hidden'));
echo $form->input('Qnote.subject');
echo $form->input('Qnote.body', array('rows' => '3'));
echo $form->input('Step.id', array('type' => 'hidden'));
echo $form->input('Step.user_id', array('value' => $userID, 'type' => 'hidden'));
echo $form->input('Step.body', array('rows' => '3'));
echo $form->end('Save Notes');
?>
This Form Adds Data in 2 Models.
Model 1 = Qnote;
Model 2 = Step;
I am able to add Data to the Models.
I was wondering I could add a button to the form
The Button would allow users to add multiple Step.data to the Step model.
Some like a +1 Button.
Basically I want to add multiple steps Per Qnote.
Could someone point me in the right direction how i can achieve this.
This is something I would do with jQuery. Basically all you need to do is using jQuery to dynamically add more inputs in the CakePHPs conventions: Step.0.user_id for example.
What you need to do now on a +1: you need to count the zero up, so you will get Step.1.user_id and so on.
First option: Use a jQuery-Script for doing this
var count = 1;
$('#add_step').click(function() {
var new_form = $('.Step').eq(0).clone();
$('input, textarea, select, radio', new_form).filter('[name^="data"]').each(function() {
var name = $(this).attr('name');
var new_name = name.replace(/\[\d*\]/, '['+count+']');
$(this).attr('name', new_name).attr('value', '');
});
$('#YourForm').after(new_form);
count+;
return false;
});
In this case you're cloning a div with the class step which holds your inputs for the model Step. You then replace the name-attribute to replace the zeros through the new value of the variable count. count++ enables you to add as many steps as you want.
This is an jQuery only solution and may require additional work for your environment.
Second option: Use AJAX with an element
You could also write a function in your StepsController which renders an element which holds your form and takes care of the counter.
Third option: Use a URL-parameter to decide how many options you want
If you have an URL like /qnote/add/3 you could use the 3 as a parameter in a for-loop to iterate through these form-inputs.
You need to take care, that eventually already typed in values are sent with the form when adding another Step so that these don't get lost.
Hope this helps to get on the right way.