How to send data to base template without controller? - symfony

I need to get the data from entity in the base template (twig), but not rendering this data from controller.
Specifically, I want to realize the menu. Menu labels stored in the database (Page entity). I have many controllers and I don't want to repeat the code of the entity handling in each controller.
I could extend the controller's classes, but I want to avoid stuff like this:
return $this->render('... .html.twig',
array(
...
'menu' => $labels,
...
)
);
in each of the controllers.

This is the perfect use-case for an embedded controller. You can call a new controller from your template for rendering a part of your response, in this case the menu. It can have any logic a controller can, meaning you can query your database, build your menu structure and render a twig file for outputting it as html.

Related

SivlerStripe field to render Javascript tags/ code

I am developing a SilverStripe project. In my project, I am trying to create a custom content block where admin can enter the Javascript code to be rendered on the front-end.
I have two field
private static $db = [
'Script' => 'Text',
'Content' => 'HTMLText',
];
(Note the Script field).
In the template, I render the variables like this.
$Script
$Content
Then in the Script textarea field, I entered the following content
<script>alert("I am the Script")</script>
When I go to the front-end page after publishing, I see this instead.
How can I create a field where I can enter Javascript code in the SilverStripe?
I’m pretty sure that you can use the raw modifier
$Script.RAW

Looking for a way to implement a polymorphic view in ASP.NET Core

I'm working on an ASP.NET MVC Core web app that would have a lot of similar views. Each view is just a simple form that has a list of label&control pairs.
An "Object" editor template has been built in order to generate the content of such views automatically based on view model properties.
Each view would basically have just one line of code:
#Html.EditorFor(m => m)
Each view model is derived from a base class.
Is there a way to get rid of duplicate views and controller actions?
Ideally, I'd like to have just one view where the model is the base model class and one controller action that would receive that base model.
Himanshu's comment steered me to use Partials for the child classes and use the base class as the model for the main views. You may be able to just use reflection/property annotation to populate the views according to the given Model, though I have not tried it.
What I have tried successfully is using a base class that is not abstract and thus will not duplicate properties in the child classes, then using generics like...
List<T> GetChildClasses<T>() where T : BaseClass;
which is called by the controller method and supplies the View Model, and then displaying like this...
#model MyApp.Models.BaseClass
<div class="show_base_class_properties_here">
</div>
#if(Model is ChildClass)
{
#await Html.PartialAsync("_ChildPartial", Model);
}
<div class="whatever_comes_next">
</div>
I suspect there is a better way but this works. Apparently there can only be one #model in a view file.

unable to access variables in extended view page in symfony

I'm passing values to a view page called abc.html.php using render in Symfony. Now this view page extends a header. The variable i'm passing from controller is not accessible in the extended view. Is there any way to do so ?
In symfony, the variables i pass from controller and not accessible in the view pages which are extended. In that case, i want to declare a global variable in config/packages/twig.php.
How can i define a global variable with session data ?
or is there any way to use variables of controller in extended view page ?
I tried accessing it. But it doesn't work out.
In my controller
return $this->render('abc.html.php',[
'variable' => 'some array or string',
]);
Now i'm unable to use the 'variable' in a base file which is extended in abc.html.php like this:
<?php echo $this->render('includes/base.html.php');?>
You can use render controller instead of extends or include template. you should create a function inside your controller witch render the header view then you call this function with render controller.
Now you can pass any variable to your header view from the controller.
https://symfony.com/doc/current/templating/embedding_controllers.html

FOSUserBundle: Change Password within actual project

I have successfully installed FOSUserBundle in my project and everything works as expected. However, I am struggling with how to implement it in my actual project.
I want to create the following setup:
A page displaying some user settings in one form (like newsletter subscription), the possibility to change the password in a second form and maybe also a third form to change the username.
The settings form as well as some more information is coming from an existing action in my controller and is working well.
I did try a few things but things are not really working out yet:
I copied some functionality from FOSUserBundle\Controller\ChangePasswordController\changePasswordAction() to my own action. This way I could get the change password form, create the view and pass it to my template.
I added the form to my template with {{ form_widget(form) }}. The form is being displayed and it's even working. I can change the password. However, the labels are being lost, simply reading Current, First, and Second. Also there is no error messaging showing up when the two new passwords don't match or are being left empty.
Over all I have the feeling I am probably doing this in a wrong way. Could you please help me how I should handle this task and point out where I am likely doing something stupid?
Here is the code of my action, reduced to what's important here:
# src/Acme/MyBundle/Controller/BackendController.php
public function accountAction(){
//pretty much a copy of FOSUserBundle\Controller\ChangePasswordController\changePasswordAction()
$user = $this->get('security.context')->getToken()->getUser();
$form = $this->container->get('fos_user.change_password.form');
$formHandler = $this->container->get('fos_user.change_password.form.handler');
$process = $formHandler->process($user);
if ($process) {
//password has been changed, response will be generated
}
//more stuff going on here
$moreStuff = ...
//render view
return $this->render('AcmeMyBundle:Backend:account.html.twig', array(
'form' => $form->createView(),
'moreStuff' => $moreStuff
));
}
IMO rendering more than one form in one action is not a good idea.
Always try to separate things and let an action handle only one feature.
In your twig template I suggest to use the render method :
{% render 'AcmeBundle:SomeAction' with{'param:param} %}
It will generate a GET request on the action provided with some params if needed.
Create one action that will render the twig template with subrequests :
// AcmeUserBundle:editAction
{% render 'AcmeUserBundle:changePasswordAction' %}
{% render 'AcmeUserBundle:settingsAction' %}
{% render 'AcmeUserBundle:profileAction' %}
And then you'll need to create one action per form.
For password and username modification you can also override FOSUserBundle views if your needs are only visual. If you need to add/remove a field on the form you will need to create a new service.
I sugget reading FOSUserBundle documentation about overriding :
https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/index.md#next-steps

Should I use PartialViewResult or separate method in another contoller?

I am using ASP MVC 4 framework. For example, I have 2 controllers: MainPanelController and CartController.
MainPanel controller defines methods and views for showing base main panel functions. Cart controller for example defines standard cart methods: RemoveFromCart, ClearCart, AddItemToCart etc.
Where should I define ShowCartItems method, if I want to display cart items list in main panel index page? I have two choises:
in CartController as PartialViewResult and render it in Index View of
MainPanel controller
completely define it in MainPanelController
I think showing cart items is CartController's task. Or maybe should I define ShowCartItems view in MainPanelController?
Maybe what your are looking for is RenderAction method, which provides you a way to output an action from other controller:
#{
Html.RenderAction("ShowCartItems","CartController");
}

Resources