TDBMultiSearch em Form Mestre/Detalhe Galera, mais uma dúvida. Estou montando um formulário mestre detalhe. Tenho como mestre a tabela da ESCALA (id, descricao, dataEscala) e como detalhe a tabela ESCALA_MEMBROS (id, escala_id, membro_id, funcao_id). Preciso vincular vários membros a uma determinada escala com uma função. Utilizei como base o exemplo do tutor (https://www.adianti.com.br/framework_files/tutor/index.php?cla...
MC
TDBMultiSearch em Form Mestre/Detalhe  
Galera, mais uma dúvida.

Estou montando um formulário mestre detalhe.
Tenho como mestre a tabela da ESCALA (id, descricao, dataEscala) e como detalhe a tabela ESCALA_MEMBROS (id, escala_id, membro_id, funcao_id).

Preciso vincular vários membros a uma determinada escala com uma função.
Utilizei como base o exemplo do tutor (https://www.adianti.com.br/framework_files/tutor/index.php?class=SaleMultiValueF).

Porém, no meu formulário está sendo possível incluir num único TDBMultiSearch mais de um registro. Gostaria de alterar para o comportamento ficar igual ao modelo do Tutor. Já tentei identificar como fazer pelo código fonte mas não consegui sucesso.

Segue minha classe do formulário mestre detalhe:

 
  1. <?php
  2. /**
  3. * EscalaDataForm Master/Detail
  4. * @author <your name here>
  5. */
  6. class EscalaDataForm extends TPage
  7. {
  8. protected $form; // form
  9. protected $table_details;
  10. protected $detail_row;
  11. /**
  12. * Class constructor
  13. * Creates the page and the registration form
  14. */
  15. function __construct($param)
  16. {
  17. parent::__construct($param);
  18. // creates the form
  19. $this->form = new TForm('form_EscalaData');
  20. $this->form->class = 'tform'; // CSS class
  21. $table_master = new TTable;
  22. $table_master->width = '100%';
  23. $table_master->addRowSet( new TLabel('EscalaData'), '', '')->class = 'tformtitle';
  24. // add a table inside form
  25. $table_general = new TTable;
  26. $table_general->width = '100%';
  27. $frame_general = new TFrame;
  28. $frame_general->class = 'tframe tframe-custom';
  29. $frame_general->setLegend('EscalaData');
  30. $frame_general->style = 'background:whiteSmoke';
  31. $frame_general->add($table_general);
  32. $frame_details = new TFrame;
  33. $frame_details->class = 'tframe tframe-custom';
  34. $frame_details->setLegend('Escala_Membro');
  35. $table_master->addRow()->addCell( $frame_general )->colspan=2;
  36. $row = $table_master->addRow();
  37. $row->addCell( $frame_details );
  38. $this->form->add($table_master);
  39. // master fields
  40. $id = new TEntry('id');
  41. $escala_id = new ">TDBSeekButton('escala_id', 'mvadmin', 'form_EscalaData', 'escala', 'descricao', 'escala_id', 'escalaNome');
  42. $escalaNome = new TEntry('escalaNome');
  43. $dataEsc = new TDate('dataEsc');
  44. $escala_id->setSize(100);
  45. $escalaNome->setSize(300);
  46. $escalaNome->setEditable(FALSE);
  47. // sizes
  48. $id->setSize('100');
  49. $escala_id->setSize('100');
  50. $escalaNome->setSize('200');
  51. $dataEsc->setSize('100');
  52. if (!empty($id))
  53. {
  54. $id->setEditable(FALSE);
  55. }
  56. // add form fields to be handled by form
  57. $this->form->addField($id);
  58. $this->form->addField($escala_id);
  59. $this->form->addField($escalaNome);
  60. $this->form->addField($dataEsc);
  61. // add form fields to the screen
  62. $table_general->addRowSet( new TLabel('Sequência'), $id );
  63. $table_general->addRowSet( $label_Escala = new TLabel('Escala'), array( $escala_id, $escalaNome ) );
  64. $table_general->addRowSet( new TLabel('Data'), $dataEsc );
  65. // detail
  66. $this->table_details = new TTable;
  67. $this->table_details-> width = '100%';
  68. $frame_details->add($this->table_details);
  69. $this->table_details->addSection('thead');
  70. $row = $this->table_details->addRow();
  71. // detail header
  72. $row->addCell( new TLabel('Membro') );
  73. $row->addCell( new TLabel('Função') );
  74. // create an action button (save)
  75. $save_button=new TButton('save');
  76. $save_button->setAction(new TAction(array($this, 'onSave')), _t('Save'));
  77. $save_button->setImage('ico_save.png');
  78. // create an new button (edit with no parameters)
  79. $new_button=new TButton('new');
  80. $new_button->setAction(new TAction(array($this, 'onClear')), _t('New'));
  81. $new_button->setImage('ico_new.png');
  82. // define form fields
  83. $this->form->addField($save_button);
  84. $this->form->addField($new_button);
  85. $table_master->addRowSet( array($save_button, $new_button), '', '')->class = 'tformaction'; // CSS class
  86. $this->detail_row = 0;
  87. // create the page container
  88. $container = new TVBox;
  89. $container->style = 'width: 100%';
  90. //$container->add(new TXMLBreadCrumb('menu.xml', __CLASS__));
  91. $container->add($this->form);
  92. parent::add($container);
  93. }
  94. /**
  95. * Executed whenever the user clicks at the edit button da datagrid
  96. */
  97. function onEdit($param)
  98. {
  99. try
  100. {
  101. TTransaction::open('mvadmin');
  102. if (isset($param['key']))
  103. {
  104. $key = $param['key'];
  105. $object = new EscalaData($key);
  106. $this->form->setData($object);
  107. $items = Escala_Membro::where('escala_id', '=', $key)->load();
  108. $this->table_details->addSection('tbody');
  109. if ($items)
  110. {
  111. foreach($items as $item )
  112. {
  113. $this->addDetailRow($item);
  114. }
  115. // create add button
  116. $add = new TButton('clone');
  117. $add->setLabel('Add');
  118. $add->setImage('fa:plus-circle green');
  119. $add->addFunction('ttable_clone_previous_row(this)');
  120. // add buttons in table
  121. $this->table_details->addRowSet([$add]);
  122. }
  123. else
  124. {
  125. $this->onClear($param);
  126. }
  127. TTransaction::close(); // close transaction
  128. }
  129. }
  130. catch (Exception $e) // in case of exception
  131. {
  132. new TMessage('error', $e->getMessage());
  133. TTransaction::rollback();
  134. }
  135. try
  136. {
  137. if (isset($param['id']))
  138. {
  139. // open a transaction with database 'mvadmin'
  140. TTransaction::open('mvadmin');
  141. // get the parameter $key
  142. $key = $param['id'];
  143. // instantiates object Escala
  144. $object = new EscalaData($key);
  145. $object->escalaNome = $object->escala->descricao;
  146. // fill the form with the active record data
  147. $this->form->setData($object);
  148. // close the transaction
  149. TTransaction::close();
  150. }
  151. else
  152. {
  153. $this->form->clear();
  154. }
  155. }
  156. catch (Exception $e) // in case of exception
  157. {
  158. // shows the exception error message
  159. new TMessage('error', 'Error ' . $e->getMessage());
  160. // undo all pending operations
  161. TTransaction::rollback();
  162. }
  163. }
  164. /**
  165. * Add detail row
  166. */
  167. public function addDetailRow($item)
  168. {
  169. $uniqid = mt_rand(1000000, 9999999);
  170. // create fields
  171. $membro_id = new TDBMultiSearch('membro_id[]', 'mvadmin', 'membro', 'id', 'nome');
  172. $funcao_id = new TDBMultiSearch('funcao_id[]', 'mvadmin', 'funcao', 'id', 'descricao');
  173. // set id's
  174. $membro_id->setId('membro_id_'.$uniqid);
  175. $funcao_id->setId('funcao_id_'.$uniqid);
  176. // set sizes
  177. $membro_id->setSize('200');
  178. $funcao_id->setSize('200');
  179. // set row counter
  180. $membro_id->{'data-row'} = $this->detail_row;
  181. $funcao_id->{'data-row'} = $this->detail_row;
  182. // set value
  183. if (!empty($item->membro_id)) { $membro_id->setValue( $item->membro_id ); }
  184. if (!empty($item->funcao_id)) { $funcao_id->setValue( $item->funcao_id ); }
  185. // create delete button
  186. $del = new TImage('fa:trash-o red');
  187. $del->onclick = 'ttable_remove_row(this)';
  188. $row = $this->table_details->addRow();
  189. // add cells
  190. $row->addCell($membro_id);
  191. $row->addCell($funcao_id);
  192. $row->addCell( $del );
  193. $row->{'data-row'} = $this->detail_row;
  194. // add form field
  195. $this->form->addField($membro_id);
  196. $this->form->addField($funcao_id);
  197. $this->detail_row ++;
  198. }
  199. /**
  200. * Clear form
  201. */
  202. public function onClear($param)
  203. {
  204. $this->table_details->addSection('tbody');
  205. $this->addDetailRow( new stdClass );
  206. // create add button
  207. $add = new TButton('clone');
  208. $add->setLabel('Add');
  209. $add->setImage('fa:plus-circle green');
  210. $add->addFunction('ttable_clone_previous_row(this)');
  211. // add buttons in table
  212. $this->table_details->addRowSet([$add]);
  213. }
  214. /**
  215. * Save the EscalaData and the Escala_Membro's
  216. */
  217. public static function onSave($param)
  218. {
  219. try
  220. {
  221. TTransaction::open('mvadmin');
  222. $id = (int) $param['id'];
  223. $master = new EscalaData;
  224. $master->fromArray( $param);
  225. $master->store(); // save master object
  226. // delete details
  227. Escala_Membro::where('escala_id', '=', $master->id)->delete();
  228. if( !empty($param['membro_id']) AND is_array($param['membro_id']) )
  229. {
  230. foreach( $param['membro_id'] as $row => $membro_id)
  231. {
  232. if (!empty($membro_id))
  233. {
  234. $detail = new Escala_Membro;
  235. $detail->escala_id = $master->id;
  236. $detail->membro_id = $param['membro_id'][$row];
  237. $detail->funcao_id = $param['funcao_id'][$row];
  238. $detail->store();
  239. }
  240. }
  241. }
  242. $data = new stdClass;
  243. $data->id = $master->id;
  244. TForm::sendData('form_EscalaData', $data);
  245. TTransaction::close(); // close the transaction
  246. new TMessage('info', TAdiantiCoreTranslator::translate('Record saved'));
  247. }
  248. catch (Exception $e) // in case of exception
  249. {
  250. new TMessage('error', $e->getMessage());
  251. TTransaction::rollback();
  252. }
  253. }
  254. }
  255. ?>


Curso Dominando o Adianti Framework

O material mais completo de treinamento do Framework.
Curso em vídeo aulas + Livro completo + Códigos fontes do projeto ERPHouse.
Conteúdo Atualizado!


Dominando o Adianti Framework Quero me inscrever agora!

Comentários (4)


NR

Use a função setMaxSize(1):
 
  1. <?php
  2. $membro_id->setMaxSize(1);
  3. ?>
MC

Bom dia!
Deu certo Nataniel. Muito obrigado!

Porém, estou tendo outros problemas.

Ao editar um registro, os itens não estão sendo carregados para o TMultiSearch. Fica tudo como "null" e acima da página exibe uma mensagem de erro.

Segue link com print.
imgur.com/a/y5eUS
NR

Você precisa passar um array associativo para a função setValue:
 
  1. <?php
  2. if (!empty($item->membro_id)) { $membro_id->setValue( array($item->membro_id=>'descricao') ); }
  3. ?>
MC

Perfeito. Realmente, revendo o código de exemplo estava claro.

Inclui o array associativo e também precisei criar os métodos get e set membro na classe model relacionada.

Obrigado Nataniel!