Codeception and Symfony2 multiple submit buttons - symfony

I have an application in Symfony2 that works fine. Now I'm trying to cover a certain part with tests and I've run into trouble with multiple submit buttons and Codeception Symfony2 module.
In the Symfony controller I need to see which submit button the user pressed. I use the following code:
$button = $form->getClickedButton();
if ($button->getName() === 'delete') {
//do stuff
}
And my problem is that $button var is always null when I submit the form form the Cest class. It works fine from the browser. Ive tried both the
$I->submitForm(['id' => 'appbundle_profileEdit'], [], 'appbundle_profileEdit[save]');
method and the
$I->click(['id' => 'appbundle_profileEdit_save'])
method.
The form (just the relevant parts):
<form name="appbundle_profileEdit" method="post" action="" id="appbundle_profileEdit" enctype="multipart/form-data">
<button type="submit" id="appbundle_profileEdit_save" name="appbundle_profileEdit[save]" class="btn-primary btn">
Submit
</button>
</form>

Related

How to prevent double submission in magnolia form

I tried to add a handler to Submit button
<input type="submit" value="Submit/ Soumettre" onclick='submitform(); this.disabled = true;'>
function submitform()
{
let myForm = document.getElementById('MyForm');
myForm.submit();
}
but that kills all input field validators (in my case email field validator).
Magnolia should have something for such a common use-case.
Clarification: Model class attached to "Page after submit" perform time-consuming request to service. So the user doesn't see a new page and can click submit button several times.
Instead of attaching handler on submit button I put handler on form.onsubmit
<div id='shadow' style="display: none; position: absolute; width:100%;height:100%;opacity:0.3;z-index:100;background:#000"></div>
<form id="MyForm" method="post" action="" enctype="multipart/form-data" onsubmit="blockScreen()"> ... </form>
function blockScreen(){
let elem = document.getElementById('shadow');
elem.style.display = 'block';
elem.addEventListener('click', function(){}, false);
}
That shadow blocks the screen and activated only when all validators are completed

How to dynamically set 'was-validated' class on form to show validation feedback messages with angular 5 after submit

I am using a template based form in angular. I also use bootstrap (v4) and I wish to show some validation messages when the form was submitted.
This is my form:
<form [ngClass]="{'was-validated': wasValidated}">
<div class="form-group">
<label for="name">Name</label>
<input type="text" id="name" name="name" class="form-control" [(ngModel)]="category.name" #name="ngModel" required maxlength="100"/>
<div *ngIf="name.invalid" class="invalid-feedback">
<div *ngIf="name.errors.required">
Name is required.
</div>
</div>
</div>
<button type="submit" class="btn btn-success" (click)="save()">Save</button>
</form>
My component looks as follows:
category: Category;
wasValidated: boolean = false;
ngOnInit() {
this.reset();
}
save() {
this.wasValidated = true;
this.categoriesService.createCategory(this.category).subscribe(
() => {
this.notificationService.add(notifications.category_saved, {name: this.category.name});
this.reset();
},
() => this.notificationService.add(notifications.save_category_failed)
);
}
reset() {
this.wasValidated = false;
this.category = {} as Category;
}
This works, but I have a feeling it's overly complex and more like a workaround rather than the right way. What is the best way to accomplish this?
Note: the class was-validated must be present on the form element in order to show the div with class invalid-feedback. I'm using this: https://getbootstrap.com/docs/4.0/components/forms/#validation
Note 2: I have currently no mechanism yet to prevent form submission on error. I'd like to know a good solution for that as well!
With the answer from #Chellappan V I was able to construct the solution I wanted.
I have applied to following changes:
First added #form="ngForm" to the form tag in the template. Secondly I changed the ngClass expression to reference the submitted state of the form, rather than referring to a boolean which was set to true manually when form was submitted. Last but not least I pass the form in the submit method on the save button.
<form novalidate #form="ngForm" [ngClass]="{'was-validated': form.submitted}">
<!-- form controls -->
<button type="submit" class="btn btn-success" (click)="submit(form)">Save</button>
</form>
In the component I injected the template variable in the component with #ViewChild.
#ViewChild("form")
private form: NgForm;
The submit method now takes a form parameter of type NgForm which is used to check if the form was valid before sending a request to the backend:
submit(form: NgForm) {
if (form.valid) {
this.categoriesService.createCategory(this.category).subscribe(
() => {
this.notificationService.add(notifications.category_saved, {name: this.category.name});
this.reset();
},
() => this.notificationService.add(notifications.save_category_failed)
);
} else {
this.notificationService.add(notifications.validation_errors);
}
}
Finally the reset method resets the form and the model so it can be re-entered to submit a next instance:
reset() {
this.form.resetForm();
this.category = {} as NewCategoryDto;
}

Controller action not being called on button click

I have an ASP .Net core MVC 2.0 app where I implemented a shopping cart for an e-commerce site as outlined in this video series. In the app, user can enter search queries for items which are displayed in a table. Each item in the table can be clicked on to display another page that has additional details for that item as well as a add to cart button.
The site features for searching, displaying the item results, and the details page are all implemented as actions in one controller class while the shopping cart functionality is all implemented in a separate controller class.
For some reason, when I click on the "Add to Cart" button for an item, a url of the form http://<hostname>/<controllerName>/<controllerACtion>/<id>is requested, but the corresponding controller action isn't called. This is strange because I'm using essentially the same code to call the action for adding to shopping cart as I did for displaying details. For this reason, I think the issue is related to the setup of the routes.
Here is the route setup in startup.cs:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=resortDeals}/{action=Index}/{id?}");
routes.MapRoute(
name: "shoppingcart",
template: "{controller=ShoppingCartController}/{action=AddToShopingCart}/{id?}");
});
Here is the shopping cart controller structure:
public class ShoppingCartController : Controller
{
public ViewResult Index()
{
...
}
public RedirectToActionResult AddToShopingCart(int dealId)
{
...
}
}
Below is the code for how the action is being called once the add to cart button is clicked:
<div class="addToCart text-right">
<p class="button ">
<a class="btn btn-success" id="cartButton" asp-controller="ShoppingCartController" asp-action="AddToShoppingCart" asp-route-id="#Model.RecNo">
Add to cart
</a>
</p>
</div>
What could be preventing the controller action from being called once the button is clicked?
I had an issue after publishing on the production server, when clicking on the button there was no response and I had to submit the button using Javascript.
<div class="addToCart text-right">
<p class="button ">
<button class="btn btn-success" onclick="search(#Model.RecNo)">
Add to cart
</button>
</p>
</div>
<script>
function addToCart(recNo) {
document.getElementById('cartForm').action = "/ShoppingCart/AddToShoppingCart/" + recNo;
document.getElementById('cartForm').submit();
}
</script>
I don't think you need the following route because the default route will handle the shoppingcart routes as well.
template: "{controller=ShoppingCartController}/{action=AddToShopingCart}/{id?}");
Also, try
<a class="btn btn-success" id="cartButton" asp-controller="ShoppingCart" asp-action="AddToShoppingCart" asp-route-id="#Model.RecNo">
I have removed the Controller word from asp-controller attribute
Also, change the input parameter name of AddToShopingCart method to id instead of dealId
public RedirectToActionResult AddToShopingCart(int id)
{
...
}

Call Method from View on Button click without reload

I haven't found a solution for my problem.
I am using asp.net mvc. In my View I am trying to call a Method, on a Buttonclick.
This is how the button looks like at the moment
<button type="button" id="#openButtonID" data-loading-text=" öffnen..." class="btn btn-primary" autocomplete="off" onclick="location.href='#Url.Action("Open", "Home", new {index =i} )'" disabled="#notConnected">
So every time I am clicking the button the website reloads itself.
At the website there is a camera stream which disappears for some seconds during the refresh. Now I have the task to avoid this, so the stream can been seen during the whole time. I have tried to call the method via Razor like this:
<button type="button" id="#openButtonID" data-loading-text=" öffnen..." class="btn btn-primary" autocomplete="off" onclick="#{( (GateControl.Controllers.HomeController)this.ViewContext.Controller ).Open( i );}" disabled="#notConnected">
But this just calls the Method if the view is loaded. As I tried this I set the return of the method to void.
Also I tried it like it is described like in this. Either the website is reloaded or I wasn't able to get in the method. I also tried several code snippets from stack overflow, but it wasn't working.
This is how the Method looks like
[CustomAuthorize]
public void Open( int index )
{
//some code
}
Since you already tried something with jQuery I suppose you use the library.
What you can do is to bind a click event to your button and inside that to make a GET ajax call.
You can use a "data-" attribute in your button to have your url generated on server and available on client.
<button id="button-id" class="btn btn-primary" data-loading-text=" öffnen..." data-url="#Url.Action("Open", "Home", new {index =i} )" disabled="#notConnected" autocomplete="off">
This should do it:
$("#button-id").click(function(){
var url = $("#button-id").data("url");
$.get(url , function(result) {
//do something with the result if you ever need to
});
});
This way you won't get the page refresh. You could also give us a little more details about that server method and what it does, maybe it needs some changes also.
Here is the full code I am using
<script src="~/Scripts/jquery-1.10.2.min.js" type="text/javascript"></script>
<button type="button" id="#openButtonID" data-loading-text=" öffnen..." class="btn btn-primary" autocomplete="off" data-url="#Url.Action("Open", "Home" , new {index=i+1} )" disabled="#notConnected">
Öffnen
</button><br /><br />
<script type="text/jscript">
$("##openButtonID").click(function () {
var url = $("##openButtonID").data("url");
$.get(url, function (result) {
//do something with the result if you ever need to
});
});
</script>

Form Submission on Enter Press

I have a form in my ASP .NET project that takes the users input, and appends it to a URL to search a wiki. The form works perfectly when you enter in a search term, and click the 'search' button, however when you type into the input box and hit enter, the page refreshes and the box clears.
my html
<form>
<label id="sideBarLabel"> Services
<input type="text" placeholder="Search Wiki: e.g. E911" name="queryString" id="query-string" />
</label>
Search Wiki
</form>
my js
function searchWiki(){
var siteQuery = $('#query-string').val();
window.location.href = "/dosearchsite.action?queryString=" + siteQuery;
}
Can anyone help ?
Your searchWiki() js method is only called when the evenement onclick is raised on your button, but not when your form is submitted.
There is several ways to achieve what you want:
Add a js method to catch the onsubmit event of your form:
$("form").on("submit", searchWiki());
Or add a tag on your form:
<form onsubmit="searchWiki()">
Or specify the action attribute on your form:
<form action="/dosearchsite.action">
Note that in ASP.NET, the ModelBinder will link your form inputs to your controller action parameters, using the name attribute of the inputs. That means that you should not specify them in the url yourself.
You should also declare your form using Html.BeginForm or Ajax.BeginForm if you want your form to be submitted by ajax.
#Html.BeginForm("ActionName", "ControllerName")
{
<label id="sideBarLabel">Services
<input type="text" placeholder="Search Wiki: e.g. E911" name="queryString" id="query-string" />
</label>
<input type="submit" class="button" value="Search Wiki"/>
}
This will call searchWiki when you press enter.
$('#query-string').keypress(function(event) {
if (event.keyCode == 13) {
searchWiki();
event.preventDefault();}});

Resources