Dizzy Bryan High
Dizzy Bryan High

Reputation: 2071

symfony2 Form Collections: adding new item to collection from a pre populated list

I'm building a basic fantasy football game as a base for learning symfony2 and doctrine.

i have an the following entities:

I'm currently building the player selection page.

I have a controller that gets a list of available players for selection, which is rendered as a table, each row has a button, i will use javascript so that when the selection button is clicked it will add the player to the form collection and then save the player in my ManyToMany table, when the form is submitted.

New players cannot be added or deleted they can only be selected from the list of available players.

The main page for the contest entry:

{% extends '@Design/Default/layout-main.html.twig' %}

    {% block title %}Enter Contest{% endblock %}
    {% block stylesheets %}
    {{ parent() }}
    <link href="{{ asset('bundles/design/css/homebase.css') }}" type="text/css" rel="stylesheet"/>
    <link href="{{ asset('bundles/design/css/menu.css') }}" type="text/css" rel="stylesheet"/>
    <link href="{{ asset('bundles/design/css/bootstrap.css') }}" rel="stylesheet"/>
    {% endblock %}
    {% block header %}
        {% include 'DesignBundle:Default/Menus:homepage-menu.html.twig' %}
        <div class="row">
            {% if app.session.flashBag.has('success') %}
                <div class="alert alert-success">
                    <a href="#" class="close" data-dismiss="alert">&times;</a>
                    {% for msg in app.session.flashBag.get('success') %}
                        {{ msg }}
                    {% endfor %}
                </div>
            {% endif %}
        </div>
        <section>
            <div  class="container">
                <div class="row jumbotron color-bkg">
                    {% include 'GameBundle:Contest/Partial:contest_details.html.partial.twig' %}
                        <div class="row">
                            <div class="col-md-6">
                                <div class="row centered-form">
                                    {{ contest.contestID }}
                                    {{ render(controller('GameBundle:FantasyPlayer:getPlayers', {'contestID': contest.contestID})) }}
                                </div>
                            </div>
                            <div class="col-md-6">
                                Select Your Team!!
                                Need to render the contestEntry Form here with the ability to add a player when a player from the list is clicked
                                In addition each added player will have a remove button to remove the player from the team.



                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </section>
    {% endblock %}
    {% block javascripts %}
        {{ parent() }}
        <script type="text/javascript">


        </script>
    {% endblock %}

The controller that gets the list of players available for selection:

class FantasyPlayerController extends Controller
{
    public function getPlayersAction($contestID)
    {
        $em = $this->get('doctrine.orm.entity_manager');

        //get the repos
        $contestRepo = $em->getRepository('GameBundle:Contest');
        $scheduleGroupRepo = $em->getRepository('GameBundle:ScheduleGroup');
        $playerRepo = $em->getRepository('DataBundle:DailyFantasyPlayer');
        $contest = $contestRepo->find($contestID);
        //var_dump($contest);die();
        //get the ScheduleGroup
        $scheduleGroup = $contest->getScheduleGroup();
        //var_dump($scheduleGroup);die();

        //get schedules
        $schedules = $scheduleGroupRepo->getScheduleGroup($scheduleGroup);
        //var_dump($schedules);die();
        //get teams playing in schedules
        $teamsArray = array();
        foreach($schedules as  $schedule){
            $hometeam = $schedule->getHomeTeam();
            $awayteam = $schedule->getAwayTeam();
            array_push($teamsArray, $hometeam);
            array_push($teamsArray, $awayteam);
        }
        //Get players matching the teams
        $dfp = $playerRepo->getAvaliablePlayersByTeam($teamsArray);

        return $this->render('GameBundle:Forms:player-list.html.twig', array(
            'dfp' => $dfp
        ));

    }

The Twig Tempate for the playerlist:

<table class="table table-condensed">
    <thead>
    <tr>
        <th>Position</th>
        <th>Player</th>
        <th>Opp</th>
        <th>Opp Rank</th>
        <th>FPPG</th>
        <th>Salary</th>
        <th></th>
    </tr>
    </thead>
    <tbody>

    {% for p in dfp %}
        <tr id="player-{{ p.playerID }}" data-player="{'position':'{{ p.position }}', 'salary': '{{ p.salary }}', 'pid': '{{ p.playerID }}'">
            <td>{{ p.position }}</td>
            <td>{{ p.name }}</td>
            <td>{{ p.team }} @ {{ p.opponent }}</td>
            <td>{{ p.opponentRank }}</td>
            <td>{{ p.opponentPositionRank }}</td>
            <td>{{ p.salary }}</td>
            <td>
                <div class="btn btn-sm btn-default player-select">Select</div>
            </td>
        </tr>
    {% endfor %}
    </tbody>
</table>

The controller is called in my twig template for entering the contest.

My ContestEntry entity has the ManyToMany Defined (its unidirectional as i only need to get players that have been assigned to a contest entry)

/**
 * ContestEntry
 *
 * @ORM\Table(name="fp_contestEntry")
 * @ORM\Entity(repositoryClass="FantasyPro\GameBundle\Entity\ContestEntryRepository")
 */
class ContestEntry
{
    public function __construct()
    {
        $this->user = new ArrayCollection();
        $this->contest = new ArrayCollection();
        $this->players = new ArrayCollection();
    }

    /**
     * @var integer
     *
     * @ORM\Column(type="integer", name="id")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var integer
     *
     * @ORM\Column(type="integer", nullable=true, name="user")
     * 
     */
    private $user;

    /**
     * @var integer
     *
     * 
     * @ORM\ManyToOne(targetEntity="FantasyPro\GameBundle\Entity\Contest", inversedBy="contestEntries")
     * @ORM\Column(type="integer", nullable=false, name="contest")
     * 
     */
    private $contest;

    /**
     * 
     * 
     * @ORM\ManyToMany(targetEntity="FantasyPro\DataBundle\Entity\Player", inversedBy="contestEntries")
     * @ORM\JoinTable(
     *     name="Player_ContestEntry",
     *     joinColumns={@ORM\JoinColumn(name="contestEntryID", referencedColumnName="id", nullable=false)},
     *     inverseJoinColumns={@ORM\JoinColumn(name="playerID", referencedColumnName="playerID", nullable=false)}
     * )
     */
    private $players;

    /**
     * @var boolean
     *
     * @ORM\Column(type="boolean", nullable=true, name="locked")
     */
    private $locked;

    /**
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @return int
     */
    public function getUser()
    {
        return $this->user;
    }

    /**
     * @param int $user
     */
    public function setUser( $user = null )
    {
        $this->user = $user;
    }

    /**
     * @return int
     */
    public function getContest()
    {
        return $this->contest;
    }

    /**
     * @param int $contest
     */
    public function setContest( $contest = null )
    {
        $this->contest = $contest;
    }

    /**
     * @return int
     */
    public function getPlayers()
    {
        return $this->players;
    }

    /**
     * @param int $players
     */
    public function setPlayers( $players = null )
    {
        $this->players = $players;
    }

    /**
     * @return boolean
     */
    public function isLocked()
    {
        return $this->locked;
    }

    /**
     * @param boolean $locked
     */
    public function setLocked( $locked )
    {
        $this->locked = $locked;
    }
}

From other questions i've read here, i need to be using a form collection.

class ContestEntryType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('user', 'hidden')
            ->add('contest', 'hidden')
            ->add('locked', 'hidden')
            ->add('players', 'collection', array(
                'type' => 'hidden',
                'allow_add' => true)
            );
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'FantasyPro\GameBundle\Entity\ContestEntry'
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'fantasypro_gamebundle_contestentry';
    }
}

Ive read the docs on symfony form collections but am having trouble understanding it, as it does not seem to give any examples of what i'm trying to do, adding a <TR> with the players information, along with a hidden field containing the playerID (to be stored in my ManyToMany Table).

Can anybody give me some pointers in the right direction?

Upvotes: 1

Views: 298

Answers (0)

Related Questions