如何以symfony形式显示字体真棒图标选择 [英] How to show font awesome icon in symfony form select
问题描述
我想在Symfony Form Builder的select选项中显示所有字体真棒图标.
I Want to show all font awesome icon in select option with Symfony Form Builder.
我将选择字段添加为:
$choices = $this->getFontAwesome();
$form->add( $key, ChoiceType::class, array('label' => 'Texte', 'choices' => $choices, 'attr' => array('class' => "fa" ) ) );
我的函数getFontAwesome();
My Function getFontAwesome();
public function getFontAwesome(){
$webroot = $this->get('kernel')->getRootDir() . '/../web';
$pattern = '/\.(fa-(?:\w+(?:-)?)+):before\s+{\s*content:\s*"\\\\(.+)";\s+}/';
$subject = file_get_contents( $webroot . '/assets/vendor/font-awesome/css/font-awesome.css');
preg_match_all($pattern, $subject, $matches, PREG_SET_ORDER);
foreach($matches as $match) {
$icons[$match[1]] = '&#x' . $match[2] . ';' ;
}
return $icons ;
}
但是在选择字段中,看不到图标:
But in the select field, don't see the icon:
字段显示代码,而不显示图标
Field show the code and not the icon
我该怎么办? 我尝试使用htmlspecialschars和其他字符(htmlentities,..),但是不起作用.
How i can do ? I Try htmlspecialschars and others ( htmlentities, .. ) but don't work.
推荐答案
If you aren't using any js plugins like Select2 or Bootstrap-select, then you have http://jsfiddle.net/NyL7d/ this possibility, but we need work a bit to reach it.
首先,要说使用<i class="fa fa-heart"></i>
作为标签不是一种选择,因为<option>
元素不能有任何子元素,而只能是文本. (查看相关问题)
First, to say that using <i class="fa fa-heart"></i>
as label isn't a choice, because the <option>
element can't have any child elements, but only text. (see related issue)
为实现可重用性,我们构建一个名为"IconChoiceType"的表单类型作为"ChoiceType"的子代:
For reusability let's build a form type named "IconChoiceType" as child of "ChoiceType":
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
class IconChoiceType extends AbstractType
{
/**
* Cache for multiple icon fields or sub-requests.
*
* @var array
*/
private $choices;
private $kernelRootDir;
public function __construct($kernelRootDir)
{
$this->kernelRootDir = $kernelRootDir;
}
public function buildView(FormView $view, FormInterface $form, array $options)
{
// Pass this flag is necessary to render the label as raw.
// See below the twig field template for more details.
$view->vars['raw_label'] = true;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'attr' => [
// It's the key of the solution and can be done in many ways.
// Now, the rendered <select> element will have a new font.
'style' => "font-family: 'FontAwesome';"
],
'choices' => $this->getFontAwesomeIconChoices(),
]);
}
public function getParent()
{
return ChoiceType::class;
}
protected function getFontAwesomeIconChoices()
{
if (null !== $this->choices) {
// don't to load again for optimal performance.
// useful for multi-icon fields and sub-requests.
return $this->choices;
}
// BTW we could configure the path to the "font-awesome.css".
$fontAwesome = file_get_contents($this->kernelRootDir.'/../web/assets/vendor/font-awesome/css/font-awesome.css');
// this regular expression only works with uncompressed version (not works with "font-awesome.min.css")
$pattern = '/\.(fa-(?:\w+(?:-)?)+):before\s+{\s*content:\s*"\\\\(.+)";\s+}/';
if (preg_match_all($pattern, $fontAwesome, $matches, PREG_SET_ORDER)) {
foreach ($matches as list(, $class, $code)) {
// this may vary depending on the version of Symfony,
// if the class name is displayed instead of the icon then swap the key/value
$this->choices['&#x'.$code.';'] = $class;
}
}
return $this->choices;
}
}
及其各自的注册服务:
# app/config/service.yml
services:
app.form.icon_choice_type:
class: AppBundle\Form\Type\ChoiceIconType
# Symfony has already a container parameter to the kernel root directory.
arguments: ['%kernel.root_dir%']
tags:
- { name: form.type }
好吧,到目前为止,没有什么与您的结果有所不同.
well, so far there is no result different from yours.
<select id="form_icon" name="form[icon]" style="font-family: 'FontAwesome';">
<option value="fa-glass"></option>
<option value="fa-music"></option>
...
</select>
问题出在哪里? <select>
字体家族已经准备好了,但是它们没有显示的图标,为什么?
Where is the problem now? The <select>
font family is ready, but the icons they aren't showing, why?
默认情况下,在Symfony中,Twig环境会转义使用 htmlspecialchars
(更多详细信息),因此我们仅需要对此表单类型覆盖此行为.为此,我们在app/Resources/views/form
目录中创建一个fields.html.twig
模板,并将此代码复制到以下位置:
By default, in Symfony the Twig environment escapes all values that are rendered using htmlspecialchars
(more details), so we need overwrite this behavior for this form type only. For that, we create a fields.html.twig
template in app/Resources/views/form
directory and copy this code inside:
{# app/Resources/views/form/fields.html.twig #}
{#
here isn't need to create the expected `icon_choice_widget` like shown
the documentation, because this looks equal to `choice_widget` from
`ChoiceType`, only we need overwrite the block that renders the label.
#}
{%- block choice_widget_options -%}
{% for group_label, choice in options %}
{%- if choice is iterable -%}
<optgroup label="{{ choice_translation_domain is same as(false) ? group_label : group_label|trans({}, choice_translation_domain) }}">
{% set options = choice %}
{{- block('choice_widget_options') -}}
</optgroup>
{%- else -%}
{# this line has been overwritten, see {{- block('choice_option_label') -}} to end #}
<option value="{{ choice.value }}"{% if choice.attr %} {% set attr = choice.attr %}{{ block('attributes') }}{% endif %}{% if choice is selectedchoice(value) %} selected="selected"{% endif %}>{{- block('choice_option_label') -}}</option>
{%- endif -%}
{% endfor %}
{%- endblock choice_widget_options -%}
{%- block choice_option_label -%}
{# this block has been called from choice_widget_options block #}
{%- if raw_label|default(false) -%}
{# the label is rendered as raw when IconChoiceType is used #}
{{ choice_translation_domain is same as(false) ? choice.label|raw : choice.label|trans({}, choice_translation_domain)|raw }}
{%- else -%}
{{ choice_translation_domain is same as(false) ? choice.label : choice.label|trans({}, choice_translation_domain) }}
{%- endif -%}
{%- endblock -%}
请注意,{{ choice.label|raw }}
原始过滤器显示存储的原始文本(这样可以避免将其转义到标签中,在这种情况下为图标字体内容.
Note that {{ choice.label|raw }}
raw filter displays the raw text stored (it prevents from being escaped) into label, in this case the icon font content.
最后,您需要注册表单主题,例如描述文档:
finally, you need to register the form theme like describe the documentation:
# app/config/config.yml
{# ... #}
twig:
form_themes:
- 'form/fields.html.twig'
结论:
$form->add('icon', IconChoiceType::class);
这篇关于如何以symfony形式显示字体真棒图标选择的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!