Child in Form Collection not submitted - symfony

I have a form with a collection field. When I submit the parent form, children added in the collection field are not submitted.
Here is what the Profiler says :
Request/Response tab :
I added a child in creneaux collection but as you can see, there isn't any child submitted in creneaux.
I don't have any error in the submitted form though.
I can't find where I'm mistaken.
Parent form :
class MiseEnLigneFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('nom', TextType::class, ['label' => 'Titre'])
->add('tempsEpreuve', TimeType::class,
['label' => 'Durée',
'label_attr' => ['class' => 'active'],
'required' => true,
'widget' => 'single_text'])
->add('creneaux', CollectionType::class,
['label' => false,
'label_attr' => ['class' => 'active'],
'entry_type' => CreneauFormType::class,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false
])
->add('polycopies', CollectionType::class,
['label' => false,
'label_attr' => ['class' => 'active'],
'entry_type' => PolycopieFormType::class,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false
]);
}
Child form :
class CreneauFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('dateDebut', DateTimeType::class, ['label' =>'Début',
'label_attr' => ['class'=>'active'],
'format' => 'dd-MM-yyyy HH:mm',
'widget' => 'single_text',
'attr' => ['data-field'=>'datetime']])
->add('dateFin', DateTimeType::class, ['label' => 'Fin',
'label_attr' => ['class'=>'active'],
'format' => 'dd-MM-yyyy HH:mm',
'widget' => 'single_text',
'attr' => ['data-field'=>'datetime']])
->add('test', CheckboxType::class, ['label' => false, 'required' => false]);
}
Controller :
$originalCreneaux = new ArrayCollection();
foreach ($colle->getCreneaux() as $creneau) {
$originalCreneaux->add($creneau);
}
$form = $this->createForm(MiseEnLigneFormType::class, $colle);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
return $this->render('Creneau/edit.html.twig', ['form' => $form->createView(),
'colle' => $colle,
'matiereName' => $matiereName]);
}
}
Twig :
{{ form_start(form) }}
<div class="card card-content">
{{ form_widget(form.nom) }}
{{ form_label(form.nom) }}
{{ form_widget(form.tempsEpreuve) }}
{{ form_label(form.tempsEpreuve) }}
</div>
<div class="card card-content">
<table class="polycopies centered"
data-prototype="{{ form_widget(form.polycopies.vars.prototype)|e }}">
<thead>
<tr>
<th>Nom</th>
<th>Supprimer</th>
</tr>
</thead>
<tbody class="poly_body">
{% for poly in form.polycopies %}
<tr>
<td>
{{ form_widget(poly.nom) }}
{{ form_label(poly.nom) }}
</td>
<td>
<a href="" class="delete_poly_link">
<i class="material-icons">delete</i>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="" id="liensAjouterPolycopies">
<a href="" class="add_poly_link btn-flat" data-tooltip="Ajouter un polycopié">
<i class="material-icons">add</i>Ajouter un polycopié
</a>
</div>
<div class="card card-content">
<span class="card-title">Créneaux</span>
<table class="creneaux centered"
data-prototype="{{ form_widget(form.creneaux.vars.prototype)|e }}">
<thead>
<tr>
<th>Date de début</th>
<th>Date de fin</th>
<th>Test</th>
<th>Supprimer</th>
</tr>
</thead>
<tbody class="creneau_body">
{% for creneau in form.creneaux %}
<tr>
<td class="center-align">
{{ form_widget(creneau.dateDebut) }}
{{ form_label(creneau.dateDebut) }}
</td>
<td class="center-align">
{{ form_widget(creneau.dateFin) }}
{{ form_label(creneau.dateFin) }}
</td>
<td class="center-align">
{{ form_widget(creneau.test) }}
{{ form_label(creneau.test) }}
</td>
<td class="center-align">
<a href="" class="delete_creneau_link">
<i class="material-icons">delete</i>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{{ form_rest(form) }}
</div>
<button class="btn-large fullwidth" type="submit" value="Sauvegarder">
<i class="material-icons left">save</i>
Enregistrer
</button>
{{ form_end(form) }}
<script>
var collectionHolder = $('table.creneaux');
var num = $('.creneau_body').children().length + 1;
jQuery(document).ready(function () {
$(document).on("click", "a.add_creneau_link", function (e) {
e.preventDefault();
addCreneauForm(collectionHolder);
return false;
});
$(document).on("click","a.delete_creneau_link", function () {
var $this = $(this);
$this.closest('tr').remove();
return false;
});
function addCreneauForm(collectionHolder) {
var prototype = collectionHolder.attr('data-prototype');
var newForm = prototype.replace(/__name__/g, num);
num += 1;
$tableau = newForm.split("<div>");
var form = '';
for (var i = 1; i < $tableau.length; i++) {
form += "<td class='center-align'>" + $tableau[i] + "</td>";
}
form += "<td class='center-align'><a href='' class='delete_creneau_link'><i class='material-icons'>delete</i></a></td>";
var $form = $('<tr></tr>').append(form);
$form.insertAfter('.creneaux tr:last');
}
</script>

There is no persist nor flush after the submit event
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($creneau);
$entityManager->flush();
Did you accidently forget ?

Related

How to add parent div with form builder in symfony

form created by form builder
<form name="post" method="post">
<div id="post">
<div class="form-group">
<input type="text" id="post_title" name="post[title]" required="required" class="form-control"/>
</div>
<div class="form-group">
<textarea id="post_content" name="post[content]" required="required" class="form-control"></textarea>
</div>
<div>
<button type="submit" id="post_postAdd" name="post[postAdd]" class="form-control btn-primary">Create</button>
</div>
<input type="hidden" id="post__token" name="post[_token]" value="ab35508c9.6MnqGe6WDVVVtkdRga_Ahtt5kDssuXri3JBx4HcVdOw.gKCQYdugYSw2_x88wN2y6Z5P_mtJyxaqm95GhkRDP52qoYFjucJOGyTuIA" />
</div>
</form>
i want this. How i create parent (div) elements one or more like below with form builder. Not in twig.
<div class="oneMore"> <!-- I need this element -->
<div class="iWantToAddThis"> <!-- I need this element -->
<div class="form-group">
...input...
</div>
<div class="form-group">
...input...
</div>
</div>
</div>
PostType.php. I created form like below.
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title', TextType::class, [
'attr' => [
'class' => 'form-control'
],
'row_attr' => [
'class' => 'form-group'
]
])
->add('content',TextareaType::class, [
'attr' => [
'class' => 'form-control'
],
'row_attr' => [
'class' => 'form-group'
]
])
->add('postAdd', SubmitType::class, [
'attr' => [
'class' => 'form-control btn-primary'
]
]);
}
_form.html.twig (I don't want to add anything in twig)
{{ form(form) }}

Use FormTheme for CollectionType?

I'm using for my symfony project the Ninsuo JqueryCollection plugin https://symfony-collection.fuz.org/symfony3/, and I have a form that has a collectionType, except that I want the targeted entity to appear with its own layout, but I do not know how to apply it to CollectionType
I have my "subform" like this
SubForm :
{{form_start(form)}}
<div class="card">
<h5 class="card-header">Nouvel utilisateur</h5>
<div class="card-body">
{{form_row(form.email)}}
<div class="row align-items-center">
<div class="col-md-4">
{{form_row(form.nom)}}
</div>
<div class="col-md-4">
{{form_row(form.prenom)}}
</div>
<div class="col-md-4">
{{form_row(form.service)}}
</div>
</div>
{{form_row(form.roles)}}
</div>
</div>
{{form_end(form)}}
And my main Form :
{{form_start(form)}}
{{form_row(form.utilisateurs, {'attr': {'class': 'my-selector jquery-buttons-collection mt-3'} })}}
<button type="submit" class="btn btn-primary">Enregistrer</button>
{{form_end(form)}}
I would like to apply the layout of the 1st form for my form.users. Someone would know how?
EDIT:
My main form :
$builder
->add('utilisateurs', CollectionType::class, [
'entry_type' => AdminUserRegistrationType::class,
'entry_options' => [
'label' => false,
],
'allow_add' => true,
'allow_delete' => true,
'delete_empty' => true,
'by_reference' => true,
'prototype' => true,
'label' => false,
'attr' => array(
'class' => 'my-selector',
'label' => false,
),
'by_reference' => false,
]);
;
With the template :
{{form_start(form)}}
{{form_row(form.utilisateurs, {'attr': {'class': 'my-selector jquery-buttons-collection mt-3'} })}}
<button type="submit" class="btn btn-primary">Enregistrer</button>
{{form_end(form)}}
The form.utilisateurs formType :
$builder
->add('nom', TextType::class)
->add('prenom', TextType::class)
->add('email', EmailType::class)
->add('service', EntityType::class, [
'class' => GroupeValidateurs::class,
'query_builder' => function (GroupeValidateursRepository $repo) {
return $repo->createQueryBuilder("g")
->orderBy("g.nom", 'ASC');
},
'choice_label' => 'nom',
'label' => "Service",
'placeholder' => 'Service'
])
->add('roles', ChoiceType::class, [
'label' => "Rôles",
'choices' => [
'Admin' => 'ROLE_ADMIN',
'Direction' => 'ROLE_DIRECTION',
'RH' => 'ROLE_RH',
],
"expanded" => true,
"multiple" => true,
])
;
And the form theme :
{% block utilisateursType_label %}{% endblock %}
{% block utilisateursType_errors %}{% endblock %}
{% block utilisateursType_widget %}
<div class="card">
<h5 class="card-header">Nouvel utilisateur</h5>
<div class="card-body">
{{form_widget(form.email)}}
<div class="row align-items-center">
<div class="col-md-4">
{{form_widget(form.nom)}}
</div>
<div class="col-md-4">
{{form_widget(form.prenom)}}
</div>
<div class="col-md-4">
{{form_widget(form.service)}}
</div>
</div>
{{form_widget(form.roles)}}
</div>
</div>
{% endblock %}
But I don't know how find the block name

Adding multi-level menu's with Timber

I am not familiar with Timber - in-fact this is the first time I've ever heard of it, but I'm helping a charity out who's web developer have left them in the lurch.
I've worked most things out - except getting sub-menu's working.
When items are added to the sub-menu location in Wordpress, they are appearing on the same level on the main menu.
Was wondering if someone could help me out?
Code is below for the various "twigs" - but let me know if you need the functions code as well to help out.
menu.twig:
{% for item in menu %}
<li class="{{ prefix }}__li {{ item.classes | join(' ') }}">
<a class="{{ prefix }}__a" target="{{ item.target }}" href="{{ item.link }}"><span>{{ item.title }}</span></a>
{% include "menu.twig" with {'menu': item.get_children} %}
</li>
{% endfor %}
{% endif %}
header.twig
<header class="header">
<div class="header__secondary">
<div class="container">
<div class="row">
<div class="col-xs-12">
<nav class="header__nav nav-secondary">
<ul class="nav-secondary__ul">
{% include "menu.twig" with {
'menu': menu.header_secondary.items,
'prefix': 'nav-secondary'
} %}
<li class="nav-secondary__li nav-secondary__li--cart">
<a class="nav-secondary__a cart-customlocation" href="{{ cart_url }}"></a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
<div class="header__primary">
{% block header %}
<div class="container">
<div class="row">
<div class="col-xs-6 col-md-2">
<a href="/" class="header__logo">
<img src="{{ site.theme.link }}/dist/img/logo.jpg" alt="{{ site.name }} Logo">
</a>
</div>
<div class="col-xs-6 col-md-10">
<nav class="header__nav nav" role="navigation">
<ul class="nav__ul">
{% include "menu.twig" with {
'menu': menu.header_primary.items,
'prefix': 'nav'
} %}
</ul>
</nav>
<div class="hamburger hamburger--spring">
<div class="hamburger-box">
<div class="hamburger-inner"></div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
</div>
</header>
functions.php
<?php
/**
* Timber starter-theme
* https://github.com/timber/starter-theme
*
* #package WordPress
* #subpackage Timber
* #since Timber 0.1
*/
if ( ! class_exists( 'Timber' ) ) {
add_action( 'admin_notices', function() {
echo '<div class="error"><p>Timber not activated. Make sure you activate the plugin in ' . esc_url( admin_url( 'plugins.php' ) ) . '</p></div>';
});
add_filter('template_include', function( $template ) {
return get_stylesheet_directory() . '/static/no-timber.html';
});
return;
}
Timber::$dirname = array('views');
Timber::$autoescape = false;
/**
* We're going to configure our theme inside of a subclass of Timber\Site
* You can move this to its own file and include here via php's include("MySite.php")
*/
class StarterSite extends Timber\Site {
/** Add timber support. */
public function __construct() {
add_action( 'after_setup_theme', array( $this, 'theme_supports' ) );
add_filter( 'timber_context', array( $this, 'add_to_context' ) );
add_filter( 'get_twig', array( $this, 'add_to_twig' ) );
add_action( 'init', array( $this, 'register_post_types' ) );
add_action( 'init', array( $this, 'register_taxonomies' ) );
add_action( 'wp_enqueue_scripts', [$this, 'load_scripts'] );
parent::__construct();
register_nav_menu('header-secondary', 'Header Secondary');
register_nav_menu('header-primary', 'Header Primary');
remove_action('woocommerce_before_main_content', 'woocommerce_breadcrumb', 20, 0); // kill woo breadcrumbs
remove_action( 'woocommerce_before_shop_loop' , 'woocommerce_catalog_ordering', 30 ); // kill woo sorting
remove_action( 'woocommerce_before_shop_loop' , 'woocommerce_result_count', 20 ); // kill woo # results
add_filter( 'woocommerce_add_to_cart_fragments', [$this, 'woocommerce_header_add_to_cart_fragment']);
add_filter( 'woocommerce_get_image_size_gallery_thumbnail', function( $size ) {
return array(
'width' => 400,
'height' => 400,
'crop' => 0,
);
});
add_action( 'after_setup_theme', function() {
add_theme_support( 'woocommerce' );
} );
}
/** This is where you can register custom post types. */
public function register_post_types() {
$name = "adoption";
$singular = "Adoption";
$plural = "Adoptions";
$labels = array(
'name' => _x("$plural", 'en'),
'singular_name' => _x("$singular", 'en'),
'all_items' => "All $plural",
'add_new' => _x("Add New $singular", 'en'),
'add_new_item' => _x("Add New $singular", 'en'),
'edit_item' => _x("Edit $singular", 'en'),
'new_item' => _x("New $singular", 'en'),
'view_item' => _x("View $singular", 'en'),
'search_items' => _x("Search $plural", 'en'),
'not_found' => _x("No $singular found", 'en'),
'not_found_in_trash' => _x("No $singular found in Trash", 'en'),
'parent_item_colon' => _x("Parent $singular:", 'en'),
'menu_name' => _x("$plural", 'en'),
);
$args = array(
'labels' => $labels,
'hierarchical' => false,
'description' => $plural,
'supports' => array(
'title',
'editor',
'thumbnail',
'revisions'
),
'taxonomies' => ['adoption_type'],
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'menu_position' => 4,
'menu_icon' => 'dashicons-welcome-view-site',
'show_in_nav_menus' => true,
'publicly_queryable' => true,
'exclude_from_search' => false,
'has_archive' => true,
'query_var' => true,
'can_export' => true,
'rewrite' => true,
'capability_type' => 'post'
);
register_post_type($name, $args);
$name = "event";
$singular = "Event";
$plural = "Events";
$labels = array(
'name' => _x("$plural", 'en'),
'singular_name' => _x("$singular", 'en'),
'all_items' => "All $plural",
'add_new' => _x("Add New $singular", 'en'),
'add_new_item' => _x("Add New $singular", 'en'),
'edit_item' => _x("Edit $singular", 'en'),
'new_item' => _x("New $singular", 'en'),
'view_item' => _x("View $singular", 'en'),
'search_items' => _x("Search $plural", 'en'),
'not_found' => _x("No $singular found", 'en'),
'not_found_in_trash' => _x("No $singular found in Trash", 'en'),
'parent_item_colon' => _x("Parent $singular:", 'en'),
'menu_name' => _x("$plural", 'en'),
);
$args = array(
'labels' => $labels,
'hierarchical' => false,
'description' => $plural,
'supports' => array(
'title',
'editor',
'thumbnail',
'revisions'
),
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'menu_position' => 4,
'menu_icon' => 'dashicons-welcome-view-site',
'show_in_nav_menus' => true,
'publicly_queryable' => true,
'exclude_from_search' => false,
'has_archive' => true,
'query_var' => true,
'can_export' => true,
'rewrite' => true,
'capability_type' => 'post'
);
register_post_type($name, $args);
if(function_exists('acf_add_options_page')) {
acf_add_options_page([
'page_title' => 'Theme Content',
'menu_title' => 'Theme Content',
'menu_slug' => 'theme-content',
'capability' => 'edit_posts',
'redirect' => false
]);
}
if(function_exists('acf_add_options_page')) {
acf_add_options_page([
'page_title' => 'Donation Settings',
'menu_title' => 'Donation Settings',
'menu_slug' => 'donation-settings',
'capability' => 'edit_posts',
'redirect' => false
]);
}
}
/** This is where you can register custom taxonomies. */
public function register_taxonomies() {
$labels = array(
'name' => 'Adoption Types',
'singular_name' => 'Adoption Type',
'menu_name' => 'Adoption Type'
);
$rewrite = array(
'slug' => 'adoptions',
'with_front' => true,
'hierarchical' => false,
);
$args = array(
'labels' => $labels,
'hierarchical' => true,
'public' => true,
'show_ui' => true,
'show_admin_column' => true,
'show_in_nav_menus' => true,
'show_tagcloud' => false,
'rewrite' => $rewrite,
);
register_taxonomy( 'adoption_type', 'adoption', $args );
}
public function load_scripts() {
wp_enqueue_style( 'main', get_stylesheet_directory_uri() . '/dist/css/main.min.css' );
wp_enqueue_script('slick-js', get_stylesheet_directory_uri() . '/dist/js/plugins/slick.min.js', 'jquery', false, true);
wp_enqueue_script('main-js', get_stylesheet_directory_uri() . '/dist/js/main.js', ['jquery', 'slick-js'], false, true);
}
/** This is where you add some context
*
* #param string $context context['this'] Being the Twig's {{ this }}.
*/
public function add_to_context( $context ) {
$context['options'] = get_fields('options');
$context['menu']['header_primary'] = new Timber\Menu('header-primary');
$context['menu']['header_secondary'] = new Timber\Menu('header-secondary');
$context['shop_url'] = get_permalink(woocommerce_get_page_id('shop' ));
$context['site'] = $this;
if (get_the_ID()) {
// load page modules
require_once('src/modules.php');
}
return $context;
}
public function theme_supports() {
// Add default posts and comments RSS feed links to head.
add_theme_support( 'automatic-feed-links' );
/*
* Let WordPress manage the document title.
* By adding theme support, we declare that this theme does not use a
* hard-coded <title> tag in the document head, and expect WordPress to
* provide it for us.
*/
add_theme_support( 'title-tag' );
/*
* Enable support for Post Thumbnails on posts and pages.
*
* #link https://developer.wordpress.org/themes/functionality/featured-images-post-thumbnails/
*/
add_theme_support( 'post-thumbnails' );
/*
* Switch default core markup for search form, comment form, and comments
* to output valid HTML5.
*/
add_theme_support(
'html5', array(
'comment-form',
'comment-list',
'gallery',
'caption',
)
);
/*
* Enable support for Post Formats.
*
* See: https://codex.wordpress.org/Post_Formats
*/
add_theme_support(
'post-formats', array(
'aside',
'image',
'video',
'quote',
'link',
'gallery',
'audio',
)
);
add_theme_support( 'menus' );
}
/** This Would return 'foo bar!'.
*
* #param string $text being 'foo', then returned 'foo bar!'.
*/
public function myfoo( $text ) {
$text .= ' bar!';
return $text;
}
/** This is where you can add your own functions to twig.
*
* #param string $twig get extension.
*/
public function add_to_twig( $twig ) {
$twig->addExtension( new Twig_Extension_StringLoader() );
$twig->addFilter( new Twig_SimpleFilter( 'myfoo', array( $this, 'myfoo' ) ) );
return $twig;
}
function woocommerce_header_add_to_cart_fragment( $fragments ) {
global $woocommerce;
ob_start();
?>
<a class="cart-customlocation" href="<?php echo $woocommerce->cart->get_cart_url(); ?>" title="<?php _e('View your shopping cart', 'woothemes'); ?>"><?php echo sprintf(_n('%d item', '%d items', $woocommerce->cart->cart_contents_count, 'woothemes'), $woocommerce->cart->cart_contents_count);?> - <?php echo $woocommerce->cart->get_cart_total(); ?></a>
<?php
$fragments['a.cart-customlocation'] = ob_get_clean();
return $fragments;
}
}
new StarterSite();
EDIT: Based on feedback received, the menu.twig code is as follows - however, not showing any menus now:
{% if items|default(menu.items) %}
<ul>
{% for item in items|default(menu.items) %}
<li class="{{ prefix }}__li {{ item.classes | join(' ') }}">
<a class="{{ prefix }}__a" target="{{ item.target }}" href="{{ item.link }}"><span>{{ item.title }}</span></a>
{% include "menu.twig" with {'menu': item.get_children} %}
</li>
{% endfor %}
</ul>
{% endif %}
EDIT 2: Below is header.twig as there's some more menu stuff in there...
<header class="header">
<div class="header__secondary">
<div class="container">
<div class="row">
<div class="col-xs-12">
<nav class="header__nav nav-secondary">
<ul class="nav-secondary__ul">
{% include "menu.twig" with {
'menu': menu.menu_header_secondary.items,
'prefix': 'nav-secondary'
} %}
<li class="nav-secondary__li nav-secondary__li--cart">
<a class="nav-secondary__a cart-customlocation" href="{{ cart_url }}"></a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
<div class="header__primary">
{% block header %}
<div class="container">
<div class="row">
<div class="col-xs-6 col-md-2">
<a href="/" class="header__logo">
<img src="{{ site.theme.link }}/dist/img/logo.jpg" alt="{{ site.name }} Logo">
</a>
</div>
<div class="col-xs-6 col-md-10">
<nav class="header__nav nav" role="navigation">
<ul class="nav__ul">
{% include "menu.twig" with {
'menu': menu.menu_header_primary.items,
'prefix': 'nav'
} %}
</ul>
</nav>
<div class="hamburger hamburger--spring">
<div class="hamburger-box">
<div class="hamburger-inner"></div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
</div>
</header>
EDIT 3 - current config after #Gchtr input and getting the correct menus to display in the correct locations. Still no sub-menus:
menu.twig:
{% set items = items|default(menu.items) %}
{% if items %}
<ul>
{% for item in items %}
<li class="{{ prefix }}__li {{ item.classes | join(' ') }}">
<a class="{{ prefix }}__a" target="{{ item.target }}" href="{{ item.link }}"><span>{{ item.title }}</span></a>
{% if item.children %}
{% include "menu.twig" with { items: item.children } %}
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
header.twig:
<header class="header">
<div class="header__secondary">
<div class="container">
<div class="row">
<div class="col-xs-12">
<nav class="header__nav nav-secondary">
<ul class="nav-secondary__ul">
{% include "menu.twig" with {
'menu': menu_header_secondary,
'prefix': 'nav-secondary'
} %}
<li class="nav-secondary__li nav-secondary__li--cart">
<a class="nav-secondary__a cart-customlocation" href="{{ cart_url }}"></a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
<div class="header__primary">
{% block header %}
<div class="container">
<div class="row">
<div class="col-xs-6 col-md-2">
<a href="/" class="header__logo">
<img src="{{ site.theme.link }}/dist/img/logo.jpg" alt="{{ site.name }} Logo">
</a>
</div>
<div class="col-xs-6 col-md-10">
<nav class="header__nav nav" role="navigation">
<ul class="nav__ul">
{% include "menu.twig" with {
'menu': menu_header_primary,
'prefix': 'nav'
} %}
</ul>
</nav>
<div class="hamburger hamburger--spring">
<div class="hamburger-box">
<div class="hamburger-inner"></div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
</div>
</header>
functions.php (snippet of the Header Stuff instead of the whole lot):
public function add_to_context( $context ) {
$context['options'] = get_fields('options');
$context['menu_header_primary'] = new Timber\Menu( 'header-primary' );
$context['menu_header_secondary'] = new Timber\Menu( 'header-secondary') ;
$context['shop_url'] = get_permalink(woocommerce_get_page_id('shop' ));
$context['site'] = $this;
In your StarterSite class in the add_to_context() method, you’re adding your menus like so:
$context['menu']['header_primary'] = new Timber\Menu('header-primary');
$context['menu']['header_secondary'] = new Timber\Menu('header-secondary');
When you now want to use access menu.items in your Twig, that doesn’t work, because you don’t access the nested value. It should be menu.header_primary.items. To simplify this, I’d change that to use separate context entries:
$context['menu_header_primary'] = new Timber\Menu( 'header-primary' );
$context['menu_header_secondary'] = new Timber\Menu( 'header-secondary') ;
Then, for your Twig file, you’ll always need to pass a menu variable.
{% set items = items|default(menu.items) %}
{% if items %}
<ul>
{% for item in items %}
<li class="{{ prefix }}__li {{ item.classes | join(' ') }}">
<a class="{{ prefix }}__a" target="{{ item.target }}" href="{{ item.link }}"><span>{{ item.title }}</span></a>
{% if item.children %}
{% include "menu.twig" with { items: item.children } %}
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
Edit
In your header.twig, you’ll need to remove the nesting from menu include as well (menu_header_primary.items instead of menu.menu_header_primary.items. Otherwise, Timber will the take the first menu it can find.
<nav class="header__nav nav" role="navigation">
<ul class="nav__ul">
{% include "menu.twig" with {
menu: menu_header_primary,
prefix: 'nav'
} %}
</ul>
</nav>
Function.php
/**
* Regsiter Nav Menus
*/
public function theme_register_nav_menus() {
register_nav_menus( array(
'primary_menu' => esc_html__( 'Primary Menu', 'themenamehere' ),
'secondary_menu' => esc_html__( 'Secondary Menu', 'themenamehere' ),
) );
}
/** This is where you add some context
*
* #param string $context context['this'] Being the Twig's {{ this }}.
*/
public function add_to_context( $context ) {
$context['menu'] = new Timber\Menu();
$context['secondaryMenu'] = new Timber\Menu('secondary_menu');
$context['site'] = $this;
return $context;
}
Menu.twig
{% if menu %}
<ul>
{% for item in items %}
<li class="{{ item.classes | join(' ')}}">
{# <a target="{{ item.target}}" href="{{ item.link}}">{{ item.title}}</a> #}
<a target="_self" href="{{ item.link}}">{{ item.title}}</a>
{% include "menu.twig" with{'items':item.children} %}
</li>
{% endfor %}
</ul>
{% endif %}
After that include that file inside Twig file bascically in base.twig file:
For Primary Menu Code looks like:
{% include "menu.twig" with{'items':menu.get_items} %}
For Secondary Menu Code looks like:
{% include "menu.twig" with{'items':secondaryMenu.get_items} %}
it looks like you are missing <ul></ul> wrapper or you haven't posted the code in the entire:
{% if menu %}
<ul>
{% for item in menu %}
<li class="{{ prefix }}__li {{ item.classes | join(' ') }}">
<a class="{{ prefix }}__a" target="{{ item.target }}" href="{{ item.link }}">{{ item.title }}</a>
{% include "menu.twig" with {'items': item.children} %}
</li>
{% endfor %}
</ul>
{% endif %}

Symfony: how to create forms dynamically in a foreach loop

I have a form that contains a hidden field, it uses this field to send a variable that indicates the id of the item to remove, to the action. I have a table that displays the content of the database table 'profil', for every line there is a button "supprimer" that deletes this line, but as i said, it only deletes the first line. Apparentlu this loop creates only one form for the first item, so I want to create this form for every item in the table.
{% if profils %}
<div id="prof_table">
<table style="background-color: #f9f9f9;position: absolute;top:10vmin;left: 5vmin;"
class="table table-responsive table-bordered">
<tr>
<th style="color: #1b6d85"> Identificateur </th>
<th style="color: #1b6d85"> Libellé</th>
<th style="color: #1b6d85"> Actions</th>
</tr>
{% for profil in profils %}
<tr><td>{{ profil.id }}</td><td>{{ profil.libelle }}</td>
<td>
<button id="delete" class="btn btn-danger btn-xs">
<a data-fancybox data-src="#hidden-content3" href="javascript:;"
style="color: #ffffee;text-decoration: none;">Supprimer</a>
</button>
</td></tr>
<!-- HERE IS THE POPUP FORM TO DELETE PROFILES-->
<div style="display: none; height: 40vh; width: 30vw;" id="hidden-content3">
<span style="position:relative;top:10vmin;font-size: medium;"></span>
{% if form3 %}
<label style="display:inline-table;">
<span style="font-size: medium;">Etes vous surs de vouloir supprimer ce profil?</span>
</label>
</section>
{{ form_start(form3, { attr: {novalidate: 'novalidate'} }) }}
<section class="col-lg-9 col-md-9 col-sm-9 col-xs-9" style="position: relative; left: 5vmin;top: 6vmin">
<label style="display:inline-table;">
<span>{{form_widget(form3.idprof, {attr: { value : profil.id}} )}}</span>
</label>
</section>
<section class="col-lg-5 col-md-5 col-sm-5 col-xs-5" style="position: relative; left: 5vmin;top: 6vmin">
<span>{{ form_widget(form3.Confirmer) }}</span>
</section>
{{ form_end(form3) }}
{% endif %}
</div>
{% endfor %}
</table>
</div>
{% else %}
{{ "Aucun profil n'a été trouvé." }}
{% endif %}
/**
* #Route("/webmaster/gestProf/{idprof}", defaults={"idprof": 0},name="gestProf")
* Method ("POST")
* #Template()
*/
public function gestProfAction(Request $request)
{
$session = new Session();
$session->start();
$em=$this
->getDoctrine()
->getManager();
$repository = $em->getRepository("CNAMCMSBundle:profil");
$profils = $repository->findAll();
foreach ($profils as $prof) {
$id = $prof->getId();
$libelle = $prof->getLibelle();
}
$prof = new profil();
$form3 = $this->createFormBuilder($prof, array('csrf_protection' => false))
->setMethod("POST")
->add('idprof', 'hidden', array('mapped' => false))
->add('Confirmer', 'submit', array('attr' => array('class' => 'btn btn-primary btn-block rounded_btn', 'id' => 'login_btn',
'style' => "width:6vw;height:5vh;padding:0px 0px; position:relative;left:5vmin;top:1vmin;font-size:2vmin;")))
->getForm();
$form3->handleRequest($request);
if ($form3->isSubmitted()) {
//$idprof = $request->request->get('idprof');
$idprof = $form3->get('idprof')->getData();
$repository = $em->getRepository("CNAMCMSBundle:profil");
$prof = $repository->findOneById($idprof);
$em=$this
->getDoctrine()
->getManager();
$em->remove($prof);
$em->flush();
}
var_dump($request->getContent());
return $this->render('CNAMCMSBundle:Default:gestProf.html.twig', array('profils'=>$profils,
'form3'=>$form3->createView()
));
}

Symfony2.7 form not valid

I'm developping a blog using Symfony 2.7. I've an ArticleBundle and a CommentBundle. My entities Article and Comment are linked by a ManyToOne relation.
When I try to send a comment, it fails. The $form->isValid() method returns false.
Here, my add method to send a comment :
public function addAction(Article $article, Request $request){
$comment = new Comment();
$form = $this->createForm(new CommentType(), $comment);
$form->handleRequest($request);
if($form->isValid()){
$comment->setArticle($article);
$em = $this->getDoctrine()->getManager();
$em->persist($comment);
$em->flush();
return $this->redirect($this->generateUrl('esgi_article_view', array(
'id' => $article->getId()
)));
} else{
return $this->render('ESGICommentBundle:Comment:add.html.twig', array(
'form' => $form->createView(),
'article' => $article
));
}
}
My comment form is inclued into article's view like this :
{{ render(controller("ESGICommentBundle:Comment:add", { 'id' : article.id })) }}
And here my form :
{{ form_start(form) }}
<div class="form-group">
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-8">
{{ form_label(form.author, "Auteur") }}
{{ form_widget(form.author, { 'attr' : { 'class' : 'form-control' } }) }}
{{ form_errors(form.author) }}
</div>
</div>
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-8">
{{ form_label(form.email, "Email (optionnel)") }}
{{ form_widget(form.email, { 'attr' : { 'class' : 'form-control' } }) }}
{{ form_errors(form.email) }}
</div>
</div>
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-8">
{{ form_label(form.content, "Commentaire") }}
{{ form_widget(form.content, { 'attr' : { 'class' : 'form-control' } }) }}
{{ form_errors(form.content) }}
</div>
</div>
</div>
<button class="btn btn-success" type="submit">Poster</button>
{{ form_end(form) }}
Thanks, have a nice day !
IF you submit the form, you should have all the errors in the profiler bar(there is a form icon which you can click to see errors in the submitted form)

Resources