Using Symfony2 and AngularJS together in one project

Why is this useful?

Today our post is dedicated to using Symfony2 and AngularJS in one project. Using AngularJS in a Symfony2 project is sometimes both appropriate and very convenient. For example, you can use it in the admin panel of your app to achieve the edit of an irregular shape. It increases development speed and makes the whole process easier.

Step 1: Create and Connect the AngularJS Module

Application.js

In this module a controller called BaseCtrl is created immediately, which will be present everywhere. It contains a global variable $rootScope.spinner, which enables and disables spinner output when the app performs a query or is busy with something.

Now we’ll connect it to the existing app. In the template twig, which extends to all subsidiary templates, add the following:
1. In tag <html> add attribute: ng-app=”DemoEkBlog”
2. In the top level block add attribute: ng-controller=”BaseCtrl”
In result we should have:
base.twig.html

Step 2: Avoiding Problems

After we’ve done these steps, a problem appears – AngularJS took control over the forms and they stop sending. To fix this problem we need to override the theme for forms. For this, go to the app/config/config.yml file and add the following value:
twig:
    form_themes:
        – ‘AppBundle::Form/form_override.html.twig’

Now we create a file called src/AppBundle/Resources/views/Form/form_override.html.twig with the following content:
form_override.html.twig

It makes the attribute action mandatory for forms. In the input field, it adds ng-model and ng-init attributes. ng-model coincides with the name attribute. ng-init records the variable value corresponding to the model of the input field. For example, before our changes the field looks like this:
<input type=”text” id=”unit_metric” name=”unit[metric]” required=”required” maxlength=”255″ value=”0.3969″ />

and after our changes it looks like this:
<input type=”text” ng-init=”metric = ‘0.3969’” ng-model=”metric” id=”unit_metric” name=”unit[metric]” required=”required” maxlength=”255″ value=”0.3969″ />
Also in the block for every field we add the class form_row, which will help facilitate styling.

Step 3: Create Simple Editor

For this we’ll create a controller called IssueEditorCtrl. It looks like a regular Angular app, except that in twig and in angular, expressions come in double braces {{}}. That’s why we must bear in mind that expressions are performed in twig first and then any that remain are performed in angular. So if we want to write {{ color.code }} in twig-template, we can do it like this:

{{ ‘{{ color.code }}’ }}.

Also we need to initialise the editor with the original data. For this we add to the controller the attribute ng-init=”init({{ initData|json_encode }})”. After implementing twig-template we will receive a call from the init() function, which will contain data in the JSON format.
This function is performed immediately when the page loads in the browser and the controller IssueEditorCtrl gets the actual data.

Example template:
edit.html.twig

Example controller (angular):
IssueEditorCtrl.js

As you can see, data is sent to Routing.generate(‘issue_save’, {id: $rootScope.issue.id}). An address like this is generated with the help of the FOSJsRoutingBundle bundle (we connected it before in the file base.twig.html). We also need to consider that the data is sent not as ‘form-data’, but as JSON text. This means that JSON is what arrives in symfony. That’s why I recommend connecting the json-form bundle.

Example controller (symfony):
IssueController.php

Disadvantages:
1) Inconveniently describes expressions for angular in twig template
2) Angular is not initialized instantly (less than half a second after the page loads) and it could happen that when the page has been formed and a user is changing something in the form, at that exact point angular initialises and the form becomes the same as it was a second before. This issue doesn’t need to be a problem though, we can fix it with stylization. Just add into the template form the attribute ng-cloak. After that, add into the style something like this:
[ng-cloak] {display: none; }

Advantages :
1) It accelerates the speed of development
2) Improves the structure and simplicity of the code
3) Is suitable for both unusual tasks and for minor problems.

Happy coding!