Passing javascript variables to twig path
Today we will describe an important "headache" that we sometimes face when the problem is: "how to insert the value of a javascript variable (or a variable that changes dynamically within a page) into a twig path"?
This is not as rare as it may seems and the real headache occurs when we need to pass a JS variable as a TWIG path variable. Let's see a quick description of the problem. Assume that we have a controller that takes as an argument a page id and returns the page content. We expect the routing to be something like:
The controller function could be something like showAction($pageId), and ask for an object from an imaginary page table, etc. etc.
Let's assume right now that we have a page that lists all the pages and when we click on each one we are able to navigate to the page itself (easy..).
But what we do if we are asked to create a dropdown (select) with the list of pages and when I select one page then I should automatically redirect to this page?
What I need is to create the dropdown, add a JS action (probably onChange is OK) and when this action is triggered I must check which is the selection and call a JS function in order to trigger the redirect (eg. window.location). Everything is good and the procedure sounds nice but one of the aforementioned steps include the path to the redirect page which is created like that:
and it is more than well known that "it is impossible to put JS code into these TWIG brackets" (at least without any add-on).
What we need here is a simple solution for our problem. If we drill a little bit to what the TWIG produce do we will realize that it creates paths according to the pattern. This means that unless we have a restriction for our variable {pageId} we should be able to pass anything as a variable to the TWIG template, meaning that all of the following should be correct as expressions:
First we set our pathToRedirect variable:
Right now, pathToRedirect holds something like: "/ABCDEF/show". So when we "catch" a change from the dropdown list and we have the value of the page to follow what we need to do in order to have the correct route is to replace the "unused pattern" with the selected Id.
Voila!
So the next time someone stops you at the street and asks you how to insert a JS variable into a TWIG path you have the answer!
This is not as rare as it may seems and the real headache occurs when we need to pass a JS variable as a TWIG path variable. Let's see a quick description of the problem. Assume that we have a controller that takes as an argument a page id and returns the page content. We expect the routing to be something like:
demo_page_show:
pattern: /{pageId}/show
defaults: { _controller: "DemoOlympiacosFCBundle:Page:show" }
The controller function could be something like showAction($pageId), and ask for an object from an imaginary page table, etc. etc.
Let's assume right now that we have a page that lists all the pages and when we click on each one we are able to navigate to the page itself (easy..).
But what we do if we are asked to create a dropdown (select) with the list of pages and when I select one page then I should automatically redirect to this page?
What I need is to create the dropdown, add a JS action (probably onChange is OK) and when this action is triggered I must check which is the selection and call a JS function in order to trigger the redirect (eg. window.location). Everything is good and the procedure sounds nice but one of the aforementioned steps include the path to the redirect page which is created like that:
{{ path('demo_page_show', {'pageId': 2} ) }}where "2" is the actual ID of the page to redirect.
and it is more than well known that "it is impossible to put JS code into these TWIG brackets" (at least without any add-on).
What we need here is a simple solution for our problem. If we drill a little bit to what the TWIG produce do we will realize that it creates paths according to the pattern. This means that unless we have a restriction for our variable {pageId} we should be able to pass anything as a variable to the TWIG template, meaning that all of the following should be correct as expressions:
{{ path('demo_page_show', {'pageId': 2} ) }}and if we try to see what is the result that they produce we will realize that it is a string that will be something like the following (for each one of the aforementioned):
{{ path('demo_page_show', {'pageId': 'two'} ) }}
{{ path('demo_page_show', {'pageId': 'two-zero'} ) }}
{{ path('demo_page_show', {'pageId': 'CL'} ) }}
/2/showWe are very close to our solution... In the aforementioned procedure of selecting from a dropdown and redirecting, our problem was how to dynamically set the pageId variable into the TWIG path. Well, we will NOT. What we will do as a solution is to set a global (or not) JS variable as the path to redirect but set as page an "unused pattern". Then, whenever a change is done to the dropdown, we will collect the ID of the selection on REPLACE the "unused pattern" to the "path to redirect" variable. After that, we should be able to have the correct path of redirect!
/two/show
/two-zero/show
/CL/show
First we set our pathToRedirect variable:
var pathToRedirect = {{ path('demo_page_show', {'pageId': 'ABCDEF'} ) }}IMPORTANT: the "unused pattern" should be something UNUSED within the constructed path.
Right now, pathToRedirect holds something like: "/ABCDEF/show". So when we "catch" a change from the dropdown list and we have the value of the page to follow what we need to do in order to have the correct route is to replace the "unused pattern" with the selected Id.
var correctId = __getTheCorrectIdFromSelectElement;
var finalPath = pathToRedirect.replace("ABCDEF", correctId);
window.location = finalPath;
Voila!
So the next time someone stops you at the street and asks you how to insert a JS variable into a TWIG path you have the answer!
Kudos to G.Adam for this solution!
Comments
Post a Comment