Send a post parameter with path - symfony

I have a list of demands, that I can remove some, so I have created a path for every demand like that:
<a href="{{ path('etudiant_suprimer_demande',{'id':demande.id} )}}
And I have a controller like that:
class EdudiantController extends Controller
{ //codes
public function suprimerdemandeAction($id){
// echo $id;
$em = $this->getDoctrine()
->getEntityManager();
$demande = $em->getRepository('AcmeEstmSiteBundle:Demande')
->find($id);
if ($demande == null) {
throw $this->createNotFoundException('Demande[id='.$id.']inexistant');
}
if ($this->get('request')->getMethod() == 'POST') {
$this->get('session')->getFlashBag()->add('info', 'Demande bien supprimée');
return $this->redirect( $this->generateUrl('acme_estm_site_espace_etudiant'));
}
//return $this->render('SdzBlogBundle:Blog:supprimer.html.twig',array('demande' => $demande));
return new Response();
}
And the routing is:
etudiant_suprimer_demande:
path: /profile/espace/suprimerdemande/{id}
defaults: { _controller: AcmeEstmSiteBundle:Edudiant:suprimerdemande }
methods: POST
What I want is do not show the id of demands in the URL, that means I want this action with a post method but I have this error:
No route found for "GET /profile/espace/suprimerdemande/3": Method Not Allowed (Allow: POST)

TL;DR
<form action="{{ path('etudiant_suprimer_demande',{'id': demande.id} )}}" method="post">
<button type="submit">Delete</button>
</form>
Explanation
The code you have now only generates an <a> link, which when a user clicks it, his user agent sends a GET request to the server, thus the error you get.
In order to create a POST request, you need a <form>.
To answer your question regarding showing ID in the generated URL, take a look at this answer. You'll have to change your controller and routing.

Related

How to Hide parameters in URL in Symfony2

I don't want the user see the parameters in my URL.
Example :
my_route:
path: /***/{id}
defaults: { _controller: MyBundle:Default:myaction}
the route will be generated like this :
***/product/1
i want just see the
***/product
As explained in comments, the request needs something to identify the resource you want to fetch. But this has nothing to do with URL rewriting. If you want to display the slug of the resource instead of the id, do the following :
my_route:
path: /products/{slug}
defaults: { _controller: MyBundle:Default:myaction}
Then, in MyBundle/Controller/DefaultController.php :
public function myactionAction(Request $request, $slug)
{
$product = $this->getDoctrine()->getManager()->getRepository('MyBundle:Product')->findOneBy(["slug" => $slug]);
}
and when you want to create a link to this product, use
link to the product

Concrete5 validation not working on a single page

I am trying to validate a form on a single page. Below is what I've tried but $validation->test() doesn't seem to be working. It's supposed to redirect to another page upon validating the first_name field. I get stuck at this url: http://localhost/mysite/index.php/buy/process/. I am using 5.6.x. Not sure what I am doing wrong.
public function process() {
$validation = Loader::helper('validation/form');
$validation->setData($this->post());
$validation->addRequired($this->post('first_name'), 'First Name must not be empty');
if ($validation->test()) {
....
....
$this->redirect('/buy/step2');
} else {
$errorArray = $validation->getError()->getList();
$this->set('errorArray', $errorArray);
}
}
This function is called from the view:
<form enctype="multipart/form-data" id="buy" class="buy-form" method="post" action="<?php echo $this->action('process')?>">.....</form>
I had to replace
$validation->addRequired($this->post('first_name'), 'First Name must not be empty');
with
$validation->addRequired('first_name', 'First Name must not be empty');
That did it.

SonataAdminBundle show dashboard blocks depending on user

I'm using SonataAdminBundle with Symfony 2.2 and want to display the dashboard blocks depending on what user is logged in.
e.g.
Users with Group Superadmin will see blocks 'UserManagement' and 'Messages'
Users with Group Staff will see only block 'Messages'
I read the whole documentation especially the security doc but found no info on how to restrict the dashboard view. I already implemented a filter which will will show no entries in the list view of an entity class if the user's permissions are not enough.
But it would be way better to not show him the blocks at all.
Any ideas on how to do this ?
Well, for anyone running into this, I solved it by simply returning an empty Response in execute(). My use-case was one where I wanted to show a block to users with a specific role:
First I defined my service for using the security.context service like so:
sonata.block.service.foo:
class: Acme\DemoBundle\Block\FooBlockService
arguments: [ "sonata.block.service.foo", "#templating", "#doctrine", "#security.context" ]
tags:
- { name: sonata.block }
Then I defined the block service __construct() as:
//Acme\DemoBundle\Block\FooBlockService
public function __construct($name, EngineInterface $templating, $doctrine, $securityContext)
{
parent::__construct($name, $templating);
$this->doctrine = $doctrine;
$this->securityContext = $securityContext;
}
Finally, in the execute function the first thing I did was check for a specific role on the user like so:
//Acme\DemoBundle\Block\FooBlockService
public function execute(BlockContextInterface $blockContext, Response $response = null)
{
if( $this->securityContext->isGranted("ROLE_ACME_FOO") === false )
{
return new Response();
}
//... more code
This works, but it feels like a hack. Mainly, because the Block goes through all of its stages, and only on the output it return nothing, meaning overhead. A better solution would be to somehow prevent the entire Block from being loaded, based on some custom code.
In conclusion, this isn't the best way, but it worked for me!
You can restrict access to block using roles, like this:
sonata_admin:
dashboard:
blocks:
- { position: top, type: your_service_block_name, class: 'col-xs-4', roles: [ROLE_SOME_NAME_HERE_, ROLE_SOME_NAME_HERE_2] }
You can check under SonataAdminBundle:Core:dashboard.html.twig how this roles works:
{% if block.roles|length == 0 or is_granted(block.roles) %}
<div class="{{ block.class }}">
{{ sonata_block_render({ 'type': block.type, 'settings': block.settings}) }}
</div>{% endif %}

How to post parameter value to some actionlink

In my view i have 10 link every link associated with some unique value. Now i want that associated value at my controller action and from that action i want to redirect the flow to some other action based on that value.
But the condition is i dont want to display it on url.
How can i acheive this?
I tried ajax.post/#Ajax.ActionLink but doing this will not facilitate redirect to another action.
Is there anything with route i need to do?
View
<ul>#foreach (var item in Model)
{<li>
#Ajax.ActionLink(item.pk_name, "Index","Candidate", new { para1= item.para1 }
, new AjaxOptions { HttpMethod = "POST" })</li>
}</ul>
Action
[HttPost]
public ActionResult(int para1)
{
return RedirectToAction(para1,"anotherController");
}
I am getting value at para1 with ajax post(that is what i primarily needed) but here also want to redirect my application flow base on para1 value which is action name.
Confision : here i am not sure is this is the right way to do this thing. So i am asking you guys should i go for route map of working with ajax post will solve my objective.
If you only need to redirect the user based on what he clicks on without showing him the link, I believe the best way to achieve this is by client-side coding.
In my opinion there is no need to take any request through the server in order to change the page for such a low-complexity redirect.
View
// HTML
// Might be broken, been awhile since I worked with MVC
// Can't really remember if that's how you put variables in HTML
<ul id="button-list">
#foreach(var item in Model)
{
<li class="buttonish" data-para1="#item.para1">#item.pk_name</li>
}
</ul>
// JS
// I wouldn't do any server related work
$('#button-list li.buttonish').click(function(){
// Your controller and action just seem to redirect to another controller and send in the parameter
window.location.href = "/controller/method/" + $(this).data('para1');
});
I think you should make one jQuery function that is call when clicked and pass unique parameter.In that function you can use AJAX and post it on appropriate controller method.
Example:
<input type="button" id="#item.pk_name" onclick="getbuttonvalue(#item.para1);" />
In script
<script type="text/javascript">
$(document).ready(function () {
function getbuttonvalue(para1) {
$.ajax({
cache: false,
type: "POST",
dataType: 'json',
url: "/controller/method/" + para1,
success: function (data) {
}
});
}
});
</script>

Returning data to a partial view

I have a blog that has a sidebar with a partial view in it that enables users to sign up for my e-mail newsfeed. What I'm trying to do is returning the user to the page they came from after posting some data, and displaying any validation or return messages in the form's partial view.
The problem is that my partial view opens in a new window (without the lay-out). How can I fix this so it returns to my blog, with the return data in de sidebar?
This is my view:
#using Blog.Models.Entities
#model Subscriber
<header>
<h2>Subscribe</h2>
</header>
<p>Subscribe to my e-mail newsfeed.</p>
#using (Html.BeginForm("Form", "Subscription"))
{
<div class="editor-label">#Html.LabelFor(subscriber => subscriber.Email)</div>
<div class="editor-field ">#Html.EditorFor(subscriber => subscriber.Email)</div>
#Html.ValidationMessageFor(subscriber => subscriber.Email)
<input type="submit" value="Subscribe" />
<p>#ViewBag.Result</p>
}
And the relevant pieces of controller that are processing the data:
public ActionResult Form()
{
return PartialView("_Form");
}
[HttpPost]
public ActionResult Form(Subscriber subscriber)
{
if (ModelState.IsValid)
{
Subscriber foundSubscriber = _repository.Subscribers.Where(s => s.Email.Equals(subscriber.Email)).FirstOrDefault();
if (foundSubscriber != null)
{
ModelState.AddModelError("Email", "This e-mail address has already been added.");
return PartialView("_Form", subscriber);
}
_repository.SaveSubscriber(subscriber);
ViewBag.Result = "Succesfully subscribed to the newsletter.";
return PartialView("_Form");
}
ModelState.AddModelError("Email", "Please provide a valid e-mail address.");
return PartialView("_Form", subscriber);
}
When submitting a form, the browser sends an HTTP Post request to the server. The browser then displays the Response's payload. Your post Controller Action is returning a PartialView, which the browser is happily rendering (even though it doesn't have the html, head, or body tags necessary to make it truly valid HTML).
It sounds like you want the browser to keep most of your page loaded and rendered, post the form, then take the resulting HTML and only replace a portion of the loaded page. Simply put, the browser isn't smart enough to do that.
What you probably want to do is something like this:
User fills in some form data and clicks save/submit/go/whatever.
However, you don't want the browser to submit the form, because it won't preserve most of the current page the way you want.
Instead, you want the "submit" button to call some local javascript.
That local JS should bundle up the user-entered form data, craft a POST with that data as the payload, and submit the POST using Ajax. This will keep the current page loaded, while the ajax request hits your Controller Action
You controller action stays the way it is, and returns a partial view.
Your JS function that launched the Ajax call must also define a "success" function which will get called when the operation completes.
Within that success function, your javascript will grab the HTML from the response, and use it to replace the area of the page that held the original form.
I highly recommend jQuery - it will make it MUCH easier to craft the Ajax request, handle the success callback, and replace just a section of the currently-loaded page with the result. My understanding is that MS's 'unobtrubsive javascript' may also help implement this, however I don't have any direct experience with it.
Obviously, all of this will only work if the browser has javascript enabled.
I finally found the solution to the problem. I implemented it with AJAX and ended up with the following code:
_Index.cshtml
<header>
<h2>Subscribe</h2>
</header>
<p>Subscribe to my e-mail newsfeed.</p>
<div id="subscription-form">
#{Html.RenderPartial("_Form");}
</div>
_Form.cshtml
#using Blog.Models.Entities
#model Subscriber
#{
AjaxOptions ajaxOptions = new AjaxOptions
{
LoadingElementId = "loading",
LoadingElementDuration = 2000,
HttpMethod = "Post",
UpdateTargetId = "subscription-form"
};
}
<div id="loading" style="display: none;">
<p>Processing request...</p>
</div>
#using (Ajax.BeginForm("Index", "Subscription", ajaxOptions))
{
<div class="editor-label">#Html.LabelFor(subscriber => subscriber.Email)</div>
<div class="editor-field ">#Html.EditorFor(subscriber => subscriber.Email)</div>
#Html.ValidationMessageFor(subscriber => subscriber.Email)
<input type="submit" value="Subscribe" />
}
_Succes.cshtml
#using Blog.Models.Entities
#model Subscriber
<p id="subscription-result">#ViewBag.Result</p>
And the following controller action methods:
public ActionResult Index()
{
return PartialView("_Index");
}
[HttpPost]
public PartialViewResult Index(Subscriber subscriber)
{
if (ModelState.IsValid)
{
Subscriber foundSubscriber = _repository.Subscribers.Where(s => s.Email.Equals(subscriber.Email)).FirstOrDefault();
if (foundSubscriber != null)
{
ModelState.AddModelError("Email", "This e-mail address has already been added.");
return PartialView("_Form", subscriber);
}
_repository.SaveSubscriber(subscriber);
ViewBag.Result = "Succesfully subscribed to the newsletter.";
return PartialView("_Succes", subscriber);
}
ModelState.AddModelError("Email", "Please provide a valid e-mail address.");
return PartialView("_Form", subscriber);
}
I hope this will help anyone trying to achieve the same in the future. BTW, I found the solution on this blog: http://xhalent.wordpress.com/2011/02/05/using-unobtrusive-ajax-forms-in-asp-net-mvc3/.

Resources