9.3.1 – formHelper
Você nunca sabe a força que tem, até que a sua única alternativa é ser forte.
Johnny Depp
Tradução simplificada e resumida do original em:
http://book.cakephp.org/3.0/en/views/helpers/form.html
class Cake\View\Helper\FormHelper(View $view, array $config =[])
O FormHelper faz a maior parte do trabalho pesado na criação de formulários. O FormHelper foca na criação de formulários de forma rápida, de uma forma que irá agilizar a validação, re-população e layout. O FormHelper também é flexível - ele vai fazer quase tudo por você, utilizando convenções, ou você pode usar métodos específicos para obter apenas o que você precisa.
Iniciando um Formulário
Cake\View\Helper\FormHelper::create(mixed $model = null, array $options =[])
O primeiro método que você deve usar para tirar vantagem do FormHelper é o create(). Este método mostra uma tag de abertura de formulário.
Todos os parâmetros são opcionais. Caso create() seja chamado sem nenhum parâmetro, ele assume que você está construindo um form que submete para o controller atual, via URL atual. O método default para a submissão do form é o POST. Caso você chame o create dentro da view para UsersController::add(), com $this->Form->create()
você deve ver a seguinte saída na view renderizada:
/<form method="post" action="/users/add">
Se create()
é chamado sem parâmetros fornecidos, assume-se a construção de um formulário que submete dados via POST para a action add()
(ou edit()
no caso de um id
estar incluído nos dados do formulário).
O argumento $model é usado como forma de contexto. Existem vários contextos embutidos para formulário e você pode adicionar seu próprio, o que nós vamos cobrir na próxima seção. O provedores internos mapeiam para os seguintes valores de $model:
- Uma instância de entidade ou um mapa de iterator para o EntityContext, neste contexto permite FormHelper trabalhar com os resultados do ORM embutido.
- Um array que contém a chave de esquema, mapeia para ArrayContext que permite a criação de estruturas de dados simples para construir forms contra.
- null e false mapeiam para o NullContext, esta classe de contexto simplesmente satisfizer a interface que a FormHelper requer. Este contexto é útil se você quiser construir um pequeno formulário que não requer persistência ORM.
Para criar um form para uma entity faça o seguinte:
// Se você está em /articles/add // $article deve ser uma entidade vazia de Article. echo $this->Form->create($article);
Isto irá postar os dados do formulário para o action add () de ArticlesController. No entanto, você também pode usar a mesma lógica para criar um formulário de edição. O FormHelper utiliza o objeto de entidade para detectar automaticamente se criará um form de adicionar ou editar. Se a entidade fornecido não é "novo", o formulário será criado como um formulário de edição. Se for novo será add.
Por exemplo, se navegar para
http://example.org/articles/edit/5, nós devemos fazer o seguinte:
// src/Controller/ArticlesController.php:
public function edit($id = null)
{
if (empty($id)) {
throw new NotFoundException;
}
$article = $this->Articles->get($id);
// Save logic goes here
$this->set('article', $article);
}
// View/Articles/edit.ctp:
// Since $article->isNew() is false, we will get an edit form
<?= $this->Form->create($article) ?>
Mudando o Método para o Form
echo $this->Form->create($article, ['type' => 'get']);
Quando existir algum campo do tipo file, precisará ser assim:
echo $this->Form->create($article, ['type' => 'file']);
Configurando a URL para o Form
echo $this->Form->create($article, ['url' => ['action' => 'login']]);
Caso o desejado form action não seja do controller atual, podemos especificar a completa URL para a action do form:
echo $this->Form->create(null, [ 'url' => ['controller' => 'Articles', 'action' => 'publish'] ]);
Ou pode apontar para uma URL externa:
echo $this->Form->create(null, [ 'url' => 'http://www.google.com/search', 'type' => 'get' ]);
Criando Controles para Forms
Cake\View\Helper\FormHelper::control
(string $fieldName, array $options = [])
$fieldName
– O nome do campo do form 'Modelname.fieldname'
.
$options
- Um array opcional que pode incluir ambos Options for Control, e options dos outros métodos (que o control()
emprega internamente para gerar vários elementos HTML) como também atributos HTML válidos.
Em versões anteriores o Cake usava $this->form->input(), agora usa $this->form->control().
O método control() permite gerar todos os controles/inputs do formulário. Esses controles incluirão uma div para quebra automática, um rótulo, um widget de controle e validação de erro, se necessário. Usando os metadados no contexto do formulário, esse método escolherá um tipo de controle apropriado para cada campo. Internamente control() usa os outros métodos do FormHelper.
Observe que enquanto os campos gerados pelo método control() são chamados genericamente de “inputs” nesta página, tecnicamente falando, o método control() pode gerar não apenas todos os elementos de tipo input do HTML, mas também outros elementos de formulário HTML (por exemplo, selects, button, textarea).
Por default o método control()
deve
empregar os
s
eguintes
widget
templates:
'inputContainer' => '<div class="input {{type}}{{required}}">{{content}}</div>' 'input' => '<input type="{{type}}" name="{{name}}"{{attrs}}/>'
Em caso de validação de erros ele também usa:
'inputContainerError' => '<div class="input {{type}}{{required}} error">{{content}}{{error}}</div>'
O tipo de controle criado (quando nós não provemos nenhum options adicional para especificar o tipo de elemento gerado) é inferido via introspecção do model e depende do tipo de dados do campo:
- Column Type - Resulting Form Field
- string, uuid (char, varchar, etc.) - text
- boolean, tinyint(1) - checkbox
- decimal - number
- float - number
- integer - number
- text - textarea
- text, with name of password, passwd - password
- text, with name of email - email
- text, with name of tel, telephone, or phone - tel
- date - day, month, and year selects
- datetime, timestamp - day, month, year, hour, minute, and meridian selects
- time - hour, minute, and meridian selects
- binary - file
O parâmetro $options
segue sua escolha de um controle específico tipo caso necessite:
echo $this->Form->control('published', ['type' => 'checkbox']);
Exemplo de form:
Crie uma nova view em um template, chamada form.ctp, contendo
<?php
echo $this->Form->create($user);
// The following generates a Text input
echo $this->Form->control('username');
// The following generates a Password input
echo $this->Form->control('password');
// Assuming 'approved' is a datetime or timestamp field the following
//generates: Day, Month, Year, Hour, Minute
echo $this->Form->control('approved');
// The following generates a Textarea element
echo $this->Form->control('quote');
echo $this->Form->button('Add');
echo $this->Form->end();
?>
Adicione um action ao controller correspondente, assim:
public function form()
{
$customers =$this->Customers;
$this->set(compact('customers'));
}
Então chame pelo navegador assim:
http://localhost/clientes/controllerNome/form
Podemos especificar qualquer opção para o tipo do input e qualquer atributo HTML.
Criar um Select
Se você deseja criar um campo select enquanto usando uma relação belogTo ou hasOne você pode adicionar o seguinte para seu UsersController (assumindo que User belongTo Group):
$this->set('groups', $this->Users->Groups->find('list'));
Então na view do Template:
echo $this->Form->input('group_id', ['options' => $groups]);
Para um select em uma associação belongsToMany Groups você pode adicionar o seguinte para seu UsersController:
$this->set('groups', $this->Users->Groups->find('list'));
Na view:
echo $this->Form->input('groups._ids', ['options' => $groups]);
Se o nome do model consiste em duas ou mais palavras, por exemplo, "UserGroup", ao passar os dados usando set() você deve nomear os seus dados com um formato pluralizado e camelCase como se segue:
$this->set('userGroups', $this->UserGroups->find('list'));
Não usar input() para gerar submits
Para isso usar o método \View\Helper\FormHelper::submit().
Options do Input
$options['type']
echo $this->Form->input('field', ['type' => 'file']);
echo $this->Form->input('email', ['type' => 'email']);
$options['label']
echo $this->Form->input('name', [
'label' => 'The User Alias'
]);
Outros:
echo $this->Form->input('name', [
'label' => [
'class' => 'thingy',
'text' => 'The User Alias'
]
]);
Tipo select:
$sizes = ['s' => 'Small', 'm' => 'Medium', 'l' => 'Large'];
echo $this->Form->select('size', $sizes, ['default' => 'm']);
$options['value']
echo $this->Form->time('close_time', [
'value' => '13:30:00'
]);
echo $this->Form->select('rooms', [
'multiple' => true,
// options with values 1 and 3 will be selected as default
'default' => [1, 3]
]);
$options['empty']
echo $this->Form->select(
'field',
[1, 2, 3, 4, 5],
['empty' => '(choose one)']
);
$options['datetime']
echo $this->Form->input('time', [
'type' => 'time',
'interval' => 15
]);
Criando dois selects estáticos para os campos controller e action em Permissions/add.ctp
$options = ['Customers'=>'Customers','Groups'=>'Groups','Users'=>'Users','Permissions'=>'Permissions','Products'=>'Products','ProductItems'=>'ProductItems','value'=>'Selecione'];
echo $this->Form->input('controller',['options'=>$options,'required'=>'false', 'class'=>'col-md-12','empty'=>'Selecione']);
$options2 = ['index'=>'index','add'=>'add','edit'=>'edit','view'=>'view','delete'=>'delete'];
echo $this->Form->input('action', ['options'=>$options2,'required'=>'false', 'class'=>'col-md-12', 'empty'=>'Selecione']);
São estáticos, portanto sempre que precisar adicionar um novo controller ou action, precisa alterar este código.
Para que Html->Link permita CSS:
<?= $this->Html->Link('<span class="glyphicon glyphicon-plus"></span> Novo', ['controller'=>'Bookmaarks','action'=>'add'],
['class'=>'btn tbn-primary pull-right']);
Assim ele mostrará o código <span...</span>
Para que permita o CSS, use:
<?= $this->Html->link('<span class="glyphicon glyphicon-plus"></span> Novo', ['controller'=>'Bookmaarks','action'=>'add'],
['class'=>'btn tbn-primary pull-right', 'escape'=>false]);
Observação:
classe Html, método link. Classe com inicial maiúscula e método tudo em minúsculas.
Mudar o tipo de um campo
O Cake gerou um campo com o tipo textarea em um form.
Para mudar podemos fazer isso:
print $this->Form->input('url',['label', 'URL']);
Mudar para tipo text (campo texto) assim:
print $this->Form->input('url',['type'=>'text','label', 'URL']);
Pegando os Erros do Formulário
Uma vez sido validado, o formulário pode recuperar seus próprios erros:
$errors = $form->errors();
/* $errors contains
[
'email' => ['A valid email address is required']
]
*/
Form Helper
Form
$this->Form->control() - usado para criar elementos com o mesmo nome. Tem dois parâmetros:
Primeiro - nome do campo
Segundo - opcional, permite usar arrays com múltiplas opções
Para o CakePHP os campos do tipo data, datatime ou timestamp obrigatoriamente devem usar DEFAULT NULL:
nascimento date DEFAULT NULL
E também não podemos alterar sua validação para exigir preenchimento com notEmpty ou notBlank. Caso contrário o Cake não reconhece e não adiciona o registro.
src/Template/Clientes/add.ctp ou edit.ctp
Ano mínimo sendo 13 anos antes do atual e máximo sendo 100 anos antes do atual, ou seja, como estou em 2016 de 1916 até 2003
Select múltiplo (permite selecionar várias opções)
print $this->Form->input('pilot_ratings',[
'type' => 'select',
'class' => 'listbox',
'size' => 5,
'id' => 'pilot_ratings',
'multiple' => 'multiple',
'options' => [
['name' => 'Habilitación de Vuelo Nocturno Local', 'value' => '1'],
['name' => 'Habilitación Cat. II / Cat. III', 'value' => '2'],
['name' => 'Habilitación de Remolque de Planeador', 'value' => '5']
]
]);
src/Template/Clientes/add.ctp ou edit.ctp
Dicas sobre data e hora
Para o CakePHP os campos do tipo data, datatime ou timestamp obrigatoriamente devem usar DEFAULT NULL:
nascimento date DEFAULT NULL
E também não podemos alterar sua validação para exigir preenchimento com notEmpty ou notBlank. Caso contrário
o Cake não reconhece e não adiciona o registro.
src/Template/Clientes/add.ctp ou edit.ctp
Por padrão o Cake mostra apenas os anos de 2011 até 2021 na combo Ano.
Vamos alterar para que o ano mínimo seja 13 anos antes do atual
e máximo seja 100 anos antes do atual, ou seja, como estou em 2016,
que mostre de 1916 até 2003, mas isso deve ser pensado para atender ao requisito
da tabela/aplicativo. No nosso caso, do DNOCS, devemos usar 18 anos antes,
ou mais para o primeiro?
Criar o select controller e o action
<?php
$controls = ['Groups'=>'Groups', 'Users'=>'Users', 'Permissions'=>'Permissions', 'Customers'=>'Customers'];
$actions = ['index'=>'index','add'=>'add','edit'=>'edit','delete'=>'delete'];
echo $this->Form->input('group_id', ['options' => $groups, 'empty'=>'Grupo','class'=>'col2']);
echo $this->Form->input('controller', ['options'=>$controls,'class'=>'col2','empty'=>'Controller']);
echo $this->Form->input('action', ['options'=>$actions,'class'=>'col2','empty'=>'Action']);
?>
Actions em form
echo $form->create('Post', ['action' => 'whatever']);
echo $form->create('Post', ['url' => '/controller_name/action_name']);
echo $this->Form->create("Despesas",['url'=>'/despesas/despesas_mes']);
Quando usamos o método set() em nosso controller, definimos variáveis específicas para serem enviadas para a view/tempalte correspondente. A view/template fará com que todas as variáveis passadas estejam disponíveis no escopo do template como variáveis locais.
Mudando largura de campos
echo $this->Form->input['Busca',['type'=>'text','maxlength'=>'8','style'=>'width:50px; height:20px;']];
Criando link com o HtmlHelper:
Para o controller atual
<?= $this->Html->link(__('Lista de Usuário'), ['action' => 'index']) ?>
Para outro controller
<?= $this->Html->link(__('Lista de Usuário'), ['controller'=>'Users','action' => 'index']) ?>
Criando formulário com o FormHelper
<?= $this->Form->create($user) ?>
<legend><?= __('Editar Usuário') ?></legend>
<?php
echo $this->Form->input('username');
echo $this->Form->input('password');
echo $this->Form->input('role', ['admin'=>'Administrador','user'=>'Usuário']);
?>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
Campo input simular select em FormHelper e mudando o label:
echo $this->Form->label('Tipo'); // Criando o Label
echo $this->Form->select('role', ['user'=>'Usuário','admin'=>'Administrador'], ['default' => 'admin']);
Mais detalhes em:
http://book.cakephp.org/3.0/en/views/helpers/form.html
https://book.cakephp.org/3.0/pt/core-libraries/form.html
Comments fornecido por CComment