【问题标题】:Adding classes to all form widgets in symfony向 symfony 中的所有表单小部件添加类
【发布时间】:2011-02-24 17:47:43
【问题描述】:

我正在尝试找到一种更好的方法来为 symfony 中的表单元素分配类。目前,我似乎无法摆脱手动分配每一个。即:

$this->widgetSchema['title']->setAttribute("class","fieldInput");
$this->widgetSchema['tag_line']->setAttribute("class","fieldInput");
$this->widgetSchema['description']->setAttribute("class","fieldInput");
// etc

我尝试过的事情没有成功

1) 循环遍历 $this->widgetSchema,将其视为一个数组并为每个键设置属性

2) $this->widgetSchema->setAttribute() 但这仅将类应用于生成的标签,而不是表单元素

一定有一种方法可以在没有专门指导的情况下击中所有领域?

谁能指出我正确的方向?

【问题讨论】:

  • 为什么不使用 CSS 呢?如果一个类应用于每个表单元素有什么好处?
  • 我不喜欢为实际元素(输入/文本区域/等)甚至 ID 设置样式。重用样式的能力较低。此外,随着项目变得越来越大,特异性可能会引起头痛。我觉得如果 在表单上,​​它应该是相同的,而不是单独的 - 并且附加到它的类应该决定它的样式。输入表单的一种样式在今天可能有效,但谁知道我一个月后什么时候需要不同的东西。这样我可以避免我的 css 表变成意大利面。 Nicole Sullivan 在展示案例方面做得比我好 - bit.ly/9iu6pX
  • 我认为您对 CSS 的整个概念的理解是错误的。此外,该幻灯片是 BS。

标签: symfony1 symfony-forms


【解决方案1】:

有办法:

在 lib/widget 中创建一个 sfWidgetFormSchemaFormatter,其中包含例如 this(来自 symfonians 的代码):

class sfWidgetFormSchemaFormatterDiv extends sfWidgetFormSchemaFormatter
{
  protected
    $rowFormat       = "<div class=\"form-row%is_error%\">\n  %label%\n  %error%\n   %hel<div class='myfieldclass'%field%</div>\n p%\n%hidden_fields%</div>\n",
    $errorRowFormat  = "%errors%\n",
    $helpFormat      = '<div class="form-help">%help%</div>',
    $decoratorFormat = "\n  %content%";

  public function formatRow($label, $field, $errors = array(), $help = '', $hiddenFields = null)
  {
    return strtr(parent::formatRow($label, $field, $errors, $help, $hiddenFields), array(
      '%is_error%'    => (count($errors) > 0) ? ' field_error' : '',
      //'%is_required%' => $field,
    ));
  }
}

然后,在你的表单中,做:

$oDecorator = new sfWidgetFormSchemaFormatterDiv($this->getWidgetSchema());
$this->getWidgetSchema()->addFormFormatter('div', $oDecorator);
$this->getWidgetSchema()->setFormFormatterName('div');

然后您可以使用选择器 .myfieldclass input 或任何您想要的样式设置元素的样式,这是更改表单结构/外观的好方法。

【讨论】:

  • 这很好,但有点矫枉过正。 CSS 就足够了,生成的代码更少,并且更易于维护。
  • 您提供了一个不错的选择,但实际问题仍未得到解答。你如何将一个类注入到每个小部件中?我正在使用 CSS 框架,因此替代方案不是一个选项。
【解决方案2】:

将类应用于父元素,而不是单个元素:

模板:

<form class="my-form" action="" method="">
 // put widgets here
</form>

CSS:

.my-form select {}
.my-form input[type=text] {}
.my-form textarea {}
.my-form input[type=submit] {}
etc...

【讨论】:

  • 我不确定投反对票是否合理。如今,这种解决方案在大多数情况下都是可以接受的。 IE8 仅在特定情况下需要支持。
【解决方案3】:

我也有同样的问题。

情况 我们开始认为 CSS 和 symfony 的小部件生成之间的分离对于集成商来说是一个很大的学习曲线,我们认为必须有一种方法让集成商更加独立于开发人员。

客户总是希望拥有自定义样式的表单......然而,自定义手工制作的 !DRY 代码已经完成。我的意思是,平面设计师不会设计仅输入文本和标签的表单,他们会找到所有创造性的方式,而我们的现实是让它在框架中工作,看起来与他们设计的一样。

这就是我们考虑使用 sfWidgetFormSchemaFormatter 的原因,但是表单控制器都是不同的,我们希望能够从视图中注入样式......因为这是一个集成问题,而不是应用程序问题。本身。

解决路径 我和我的团队负责人想出了一个解决方案。主要使用部分并循环它们。表单视图可能如下所示。

我们的解决方案并不完美,因为我们想通过视图中的调用来说明哪个控制器可以获得哪个类名。但它比使用 CSS 的 input[type=text] 更好,因为我们的客户端仍然使用&lt; IE8。但至少,

所以我们想到了为什么不将字段 id 映射到一个可能具有不同行为的类名(不同于标签+输入(如果需要,当然还有 +helper+error))。

我们所做的是为那些特殊的控制器注入控制样式(例如:label+select+select+select+helper+error)假设这个 Widget 有 id some_field_id,我们需要它给父级 &lt;li&gt; .

我们可以这样做:

$node_classes_map => array('some_field_id'=>'date-selector')

所以...现在是时候编写一些代码了:

首先,我们需要使用'list' widgetFormatter:

<?php
// lib/form/SomeForm.php
class SomeForm extends BaseSomeForm
{
   public function configure()
   {
       $this->widgetSchema->setFormFormatterName('list');
   }
}

或者,您可以使用qais answer 将所有表单作为列表(终于!我以前不知道)。

观点:

<?php
// apps/appName/modules/moduleName/templates/someviewSuccess.php
$node_classes_map = array(
  'some_field_id'=>'date-selector'
   // .date-selector would have many select side by side. 
   // (no CSS for that in this example)
);
include_partial('global/patterns/formParent',
    array(
        'form'=>$form,
        'form_classes'=>'labels-on-left',
        'node_classes_map' => $node_classes_map
    )
);

formParent 看起来像:

<?php
// apps/appName/templates/_patterns/formParent.php
$form_classes_attr = (isset($form_classes))?' class="'.$form_classes.'"':'';
$form_list_node_partial = 'global/patterns/listFormDefaultNode';
$model_name_lowercase = strtolower($form->getModelName());
$node_classes_map = (isset($node_classes_map))?$node_classes_map:array();
?>
<?php use_stylesheets_for_form($form) ?>
<?php use_javascripts_for_form($form); ?>
<form action="<?php 
    echo url_for($model_name_lowercase.'/'.($form->getObject()->isNew() ? 'create' : 'update').(!$form->getObject()->isNew() ? '?id='.$form->getObject()->getId() : ''))
?>"<?php echo $form_classes_attr;
?> method="post" <?php $form->isMultipart() and print 'enctype="multipart/form-data" '?>>
<h2><?php echo __(($form->getObject()->isNew()?'new.':'edit.').$model_name_lowercase.'.form.title'); ?></h2>
<fieldset>
    <ol>
<?php
    foreach($form as $item){
        $node_classes = (isset($node_classes_map[$item->renderId()]))?$node_classes_map[$item->renderId()]:'';
        include_partial($form_list_node_partial,
            array(
                'item'=>$item,
                'node_classes' => $node_classes
            )
        );
    }
?>
    <ol>
</fieldset>
<?php echo $form->renderHiddenFields() ?>
<?php echo $form->renderGlobalErrors() ?>
<?php echo (!$form->getObject()->isNew())? '<input type="hidden" name="sf_method" value="put" />':''; ?>
</form>

每个表单元素都由自定义元素或 listFormDefaultNode 呈现。

从那里,你可以想出一个不同的部分来渲染控制器,从主流的标签+输入+帮助器+错误到更复杂的东西,比如标签+选择+选择+选择+帮助器+错误。

这是我的默认表单 *Node

<?php
// apps/appName/templates/_patterns/listFormDefaultNode.php
/**
 * Manual: http://www.symfony-project.org/forms/1_4/en/A-Widgets
 */
if(!$item->isHidden()){ ?>
<li class="<?php echo $item->renderId().((is_string($node_classes))?' '.$node_classes:''); ?>">
  <?php echo $item->renderLabel(); ?>
  <?php echo $item; ?>
  <?php echo (!!$item->renderHelp())?'<span class="helpers">'.$item->renderHelp().'</span>':''; // I did not find any hasHelper(), so switching to bool ?>
  <?php echo ($item->hasError())?'<span class="alertify error">'.$item->renderError().'</span>':''; ?>
</li>
<? }

最后,这是我的 CSS 的开始:

请注意,这是项目 CSS 的一部分,它使用了我正在使用 Snippies 开发的部分概念。去那里了解我如何构建我的 CSS 的更多想法。

/* ****** Misc ****** */
/**
 * General form views settings
 **/
form ol, form ul {
  list-style-type: none;
  padding: 0;
  margin: 0;
}
form input.text, form select {
  display: block;
  border: 0;
  padding: 4px;
  line-height: 12px;
  font-size: 15px;
}
form select {
  background-color: #e3e8eb;
  color: #506775;
  margin: 0;
}
form label {
  color: #345569;
  display: block;
  font-weight: bold;
  margin-bottom: 5px;
}
form input.text {
  color: #345569;
  border: none;
  background-color: #e3e8eb;
  color: #738996;
  border: 0px solid #c3c987;
  padding: 4px;
  line-height: 12px;
  width: 100%;
}
form fieldset {
  padding: 0;
  margin: 0;
  border: none;
  padding-bottom: 10px;
  margin-bottom: 10px;
  border-bottom: 1px solid #98a7af;
  padding: 10px 0;
}
form li {
  margin-bottom: 10px;
}
form li .helpers {
  color: #98a7af;
}
/**
 * /General form views settings
 **/


/**
 * General error messages 
 **/
.alertify {
  padding: 0.8em;
  margin-bottom: 1em;
  border: 2px solid #ddd;
}
.alertify strong, .alertify p {
  padding: 0 0 10px 0;
  display: block;
}
.alertify ul {
  margin: 0;
  padding: 0 0 0 15px;
}
.alertify ul li {
  padding: 0 0 5px 0;
}
.error, .alert {
  background: #fbe3e4;
  color: #8a1f11;
  border-color: #fbc2c4;
}
/**
 * /General error messages 
 **/
/* ****** /Misc ****** */


/* ****** Specialization ****** */
/**
 * Form labels on the left
 */
form.labels-on-left fieldset {
  padding: 0;
  margin: 0;
  padding-bottom: 10px;
  margin-bottom: 10px;
}
form.labels-on-left li {
  clear: both;
  overflow: hidden;
}
form.labels-on-left li input.text, form.labels-on-left li select {
  border: 0;
  padding: 4px;
  line-height: 12px;
}
form.labels-on-left li input.text {
  width: 815px !important;
  float: left;
  padding: 6px;
  color: #506775;
}
form.labels-on-left li select {
  background-color: #e3e8eb;
  color: #506775;
  height: 26px;
  width: 400px;
  margin: 0;
  float: left;
}
form.labels-on-left li .beside {
  float: left;
}
form.labels-on-left li .beside a {
  font-weight: bold;
  padding: 5px 20px;
  font-size: 14px;
  display: block;
}
form.labels-on-left li label {
  color: #345569;
  width: 80px;
  font-size: 120%;
  text-align: right;
  font-weight: bold;
  float: left;
  display: block;
  padding: 5px 10px 0 0;
}
form.labels-on-left li .error span, form.labels-on-left li .helpers span {
  padding: 5px;
  display: block;
}
form.labels-on-left li .helpers {
  width: 100%;
}
/**
 * /Form labels on the left
 */
/* ****** /Specialization ****** */

【讨论】:

  • 附带说明,我根本不使用 symfony1。 Twig 好多了。
【解决方案4】:

从表单类中:

foreach ($this->getWidgetSchema()->getFields() as $field)
{
  $field->setAttribute('class', 'custom-class');
}

如果您有许多需要它的表单类,您也可以从自定义 sfWidgetFormSchemaFormatter 类的构造函数中调用该代码:

public function __construct(sfWidgetFormSchema $widgetSchema)
{
    parent::__construct($widgetSchema);

    foreach ($this->getWidgetSchema()->getFields() as $field)
    {
        $field->setAttribute('class', 'custom-class');
    }
}

【讨论】:

    【解决方案5】:

    这是旧的,但对于任何试图找到它的人来说,只需进入 /lib/filter/doctrine/ 中的 xxxxxFormFilter.php 并执行以下操作:

    $this->getWidget('inputname')->setAttribute('class_name','class_name/id_name');
    

    这样你可以单独指定和控制一切。

    【讨论】:

      【解决方案6】:

      根据你扩展的基本形式,你可以在configure方法中添加以下内容:

      public function configure()
      {
          foreach ($this->widgetSchema->getFields() as $field) {
              $field->setAttribute('class','my-custom-class');
          }
          parent::configure();
      }
      

      我是在 BaseFormDoctrine 中完成的。您可以使用相同的方法来添加/覆盖字段中的任何属性,甚至可以根据字段类型添加自定义规则。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-12
        • 1970-01-01
        • 1970-01-01
        • 2015-10-19
        相关资源
        最近更新 更多