I am current using laravel 5.7 I have a form in a bootstrap modal that has 2 tabs and each tab will display its submit button respectively. I am trying to capture which submit button has been click from my controller. I have already tried using Input::get('btn-name'); and $request->submit == 'btn-name' but neither of the methods are working for me. I tried dd(Input::all()) but it did not even capture the clicked button
Update
i have tried changing both my button name to create-btn and added these in my controller and it displays "none" in the dd($action);
$action = Input::get('create-btn','none');
if($action == 'create-team'){
$project->type = 'Team';
dd($action);
}else if($action == 'create-personal'){
$project->type = 'personal';
dd($action);
}else{
dd($action);
}
HTML
The <a> tag is not inside the <form> tag is because it is located at the modal's footer hence i use an on-event function
<!--Team Tab Button-->
<button action="{{route('project.store')}}"
method="POST"
class="btn btn-primary"
name="create-btn"
value="create-team"
onclick="event.preventDefault(); document.getElementById('submit-form
personal').submit();">Createdd changes
</button>`
<!--Personal Tab Button-->
<button action="{{route('project.store')}}"
method="POST"
class="btn btn-primary"
name="create-btn"
value="create-personal"
onclick="event.preventDefault(); document.getElementById('submit-form-
personal').submit();">Createdd changes
</button>`
Controller
public function store(Request $request)
{
$this->validate($request, [
'p_name' => 'required|min:6|max:50',
'start_date' => 'required',
'end_date' => 'required',
]);
$project = new Project;
$project->p_name = $request->input('p_name');
$project->start_date = $request->input('start_date');
$project->end_date = $request->input('end_date');
$project->colab = $request->input('colab');
dd(Input::all());
if($request->submit == 'create-team'){
$project->type = 'team ';
$project->save();
}
return 123;
}
Related
I am experimenting with Laravel Livewire and I came across a situation where the previous errors are displayed even though the form is successfully submitted.
Before hit Save
After hitting Save
Html segment of name in blade file customer-new.blade.php.
<div class="form-group">
<div class="border rounded-0 px-1">
<label class="mb-0" for="name">Name</label>
<input wire:model="name" type="text" class="form-control form-control-sm " id="customer-name" aria-describedby="customer-nameHelp">
</div>
#error('name') <span class="err-message">{{ $message }}</span> #enderror
</div>
and the Save button code:
<button
wire:click="store"
wire:loading.attr="disabled"
wire:target="store"
type="submit"
class="btn btn-sm btn-light">Save
</button>
store method of CustomerNew.php:
public function store()
{
$this->validate([
'name' => 'required|max:80',
'street' => 'required|max:100',
'city' => 'required|max:40',
'dueAmount' => 'numeric|min:0'
]);
Customer::create([
'name' => $this->name,
'street' => $this->street,
'city' => $this->city,
'due_amount' => $this->dueAmount,
]);
session()->flash('message', 'Customer was saved');
$this->clear();
}
and the clear() method is like:
public function clear() {
$this - > name = '';
$this - > street = '';
$this - > city = '';
$this - > dueAmount = 0;
}
According to docs https://laravel-livewire.com/docs/input-validation,
You need to reset the validations whenever you want
Direct Error Message Manipulation The validate() and validateOnly()
method should handle most cases, but sometimes you may want direct
control over Livewire's internal ErrorBag.
Livewire provides a handful of methods for you to directly manipulate
the ErrorBag.
From anywhere inside a Livewire component class, you can call the
following methods:
$this->addError('email', 'The email field is invalid.');
// Quickly add a validation message to the error bag.
$this->resetErrorBag();
$this->resetValidation();
// These two methods do the same thing. The clear the error bag.
// If you only want to clear errors for one key, you can use:
$this->resetValidation('email');
$this->resetErrorBag('email');
$errors = $this->getErrorBag();
// This will give you full access to the error bag,
// allowing you to do things like this:
$errors->add('some-key', 'Some message');
HINT
I am using the reset methods on hydrate function like following
...
public function hydrate()
{
$this->resetErrorBag();
$this->resetValidation();
}
...
You should reset the public properties by using the livewire's reset method. Delete your $this->clear() method definition and replace it with the following:
$this->reset('name', 'street', 'city', 'dueAmount');
add id's to the error message div
#error('name') <span class="err-message" id="name-error">{{ $message }}</span> #enderror
#error('street') <span class="err-message" id="street-error">{{ $message }}</span> #enderror
#error('city') <span class="err-message" id="city-error">{{ $message }}</span> #enderror
#error('due_amount') <span class="err-message" id="due_amount-error">{{ $message }}</span> #enderror
$this->resetErrorBag();
Just add this in your clear() method. This will reset the error bag after each save.
It is better to send $name to the resetValidation and resetErrorBug. In this way you reset validation for the updating fields only. Here is my example:
public function updated($name, $value)
{
$this->resetValidation($name);
$this->resetErrorBag($name);
}
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;
}
I have a button that contains a link to another page, and pass some variables from the twig template to the controller action of that page :
<button class="btn btn-warning btn-xs" title="modifier l'article">
<i class="fa fa-pencil-square-o"></i>
</button>
The variables pass to the action successfully but I get an error :
No route found for "GET /content/articles/changeArt/3/test3/%3Ci%3E%3Cu%20style=%22background-color:%20rgb%28255,%20255,%200%29;%22%3Esdfghyujhgrertjr%22%5Ekrjthbkrkjgjgrhgiebgfjkebvkebvkezbkzbkdzbdkzbckdszb%20sdnckdzb%20nc,de%3C/u%3E%3C/i%3E/11/04/2017" (from "http://127.0.0.1/PFE_CNAM/web/content/articles")
(the variable 'content' its of type BLOB, and I start geting this error when i changed its type, because before when it was of type text,this action was working pretty good).
Here is the action code :
/**
* #Route("/content/articles/changeArt/{id}/{title}/{content}/{date}",defaults={"id": 0,"title": 0,"content": 0,"date": 0},name="changeArticle")
* #Template()
*/
public function changeArticleAction($id,$title,$content,$date)
{
$session = new Session();
$session->start();
$search = $session->get('user');
$gestAcces = $session->get('acces');
$gestEtat = $session->get('etatUser');
$gestCont = $session->get('contenu');
$repMsg = $session->get('repMsg');
$gestRec = $session->get('Reclam');
$gestMess = $session->get('gestMess');
$gestMp = $session->get('gestMp');
return $this->render('CNAMCMSBundle:Default:changeArticle.html.twig', array('search' => $search,
'contenu' => $gestCont,
'gestAcces' => $gestAcces,
'gestEtat' => $gestEtat,
'repMsg' => $repMsg,
'gestRec' => $gestRec,
'gestMess' => $gestMess,
'gestMp' => $gestMp,
'date'=>$date,
'id'=>$id,
'title'=>$title,
'content'=>$content,
));
}
Look at your route definition /content/articles/changeArt/{id}/{title}/{content}/{date} you can see this route expected exactly 4 params. Then, look at the generated path /content/articles/changeArt/3/test3/%3Ci%3E%3Cu%20style=%22background-color:%20rgb%28255,%20255,%200%29;%22%3Esdfghyujhgrertjr%22%5Ekrjthbkrkjgjgrhgiebgfjkebvkebvkezbkzbkdzbdkzbckdszb%20sdnckdzb%20nc,de%3C/u%3E%3C/i%3E/11/04/2017, it has alot of params separated by / because your params contains slashes.
When matching the URI with route path, it look like:
id: 3
title: test3
content: %3Ci%3E%3Cu%20style=%22background-color:%20rgb%28255,%20255,%200%29;%22%3Esdfghyujhgrertjr%22%5Ekrjthbkrkjgjgrhgiebgfjkebvkebvkezbkzbkdzbdkzbckdszb%20sdnckdzb%20nc,de%3C
date: u%3E%3C
i%3E // how about these extra params?
11 //
04 //
2017 //
I don't known which Symfony version you're using, it should throw exeption if your params contains /. You can solve your problem by encode your params before generate the url.
{{ path('changeArticle', {
id: id,
title: titre|url_encode,
content: corps|url_encode,
date: pub|date('d/m/Y')|url_encode
}) }}
Is 'date':pub|date('d/m/Y') a Typo?
Try this:
<button class="btn btn-warning btn-xs" title="modifier l'article">
<a
href="{{ path('changeArticle',{
'id' : id,
'title' : titre,
'content' : corps,
'date' : date|date('d/m/Y')
}) }}"
style="color: #ffffee;text-decoration: none;"><i class="fa fa-pencil-square-o"></i>
</a>
</button>
I'm doing functional testing and I am getting the error
InvalidArgumentException: The current node list is empty
This is my code
public function testThis(){
$requestContent = [
'val1' => '324343',
'valname' => '"Benjamin"',
'valLast' => '"A"',
'valnum' => '44343',
'hndval1' => '0000',
'hdnval2' => '0000',
'hndval3' => '1111',
'hndref' => '"ThisIsAtest"',
'hdnMessage' => '"I am a message"'
];
$crawler = $this->client->request('GET', '/');
$submitButton = $crawler->selectButton('btnSubmit');
$form = $submitButton->form($requestContent);
print_r($form);
$this->client->followRedirects(true);
$crawler = $this->client->submit($form);
$response = $this->client->getResponse();
$request = $this->client->getRequest();
print_r($crawler->html());
$this->assertRegExp('/\/nextPage', $request->getUri());
print_r($request->getUri());
$a = $crawler->filter('input[name="pageName"]');
$this->assertContains(
"True",
$a->attr('value')
);
}
I think it is getting error in this :
$form = $submitButton->form($requestContent);
Note that $requestContent values are coming from a hidden input type which are all inside the form tag.
You have not posted your HTML so now i assumed your HTML such as :
<html>
<form method='GET' action='your action here'>
/*
* all other html here
*/
<input type='submit' value='Submit' id='btnSubmit' name='btnSubmit'>
</form>
</html>
$submitButton = $crawler->selectButton('btnSubmit');
to change
$submitButton = $crawler->selectButton('Submit');
Because selectButton() accept the button value instead of id or name.
Make sure this is a helpful to you.
You have to provide the text of the button to $crawler->selectButton().
// For a given HTML button:
// <input type="button" value="Upload File" />
// or
// <button type="button">Upload File</button>
$crawler->selectButton("Upload File");
Side note, your regex pattern '/\/nextPage' is invalid. You need to add a closing / --> '/\/nextPage/' // This will match the exact string: "/nextPage"
Hey I am saving every page in two different languages on my website. I want to manage my pages with an admin area that I am developing with symfony2 at the moment.
Following controller code is able to display two forms on the same page containing the right data from the database. One form to manage the DE language and another for EN:
View:
<form action="{{ path('admin_about') }}" method="post" {{ form_enctype(formEN) }}>
{{ form_widget(formEN) }}
<button type="submit" class="btn btn btn-warning" naem="EN">Save</button>
</form>
<form action="{{ path('admin_about') }}" method="post" {{ form_enctype(formDE) }}>
{{ form_widget(formDE) }}
<button type="submit" class="btn btn btn-warning" name="DE">Save</button>
</form>
Controller:
public function aboutAction(Request $request)
{
$pageEN = $this->getDoctrine()
->getRepository('MySitePublicBundle:Page')
->findOneBy(array('idName' => 'about', 'lang' => 'EN'));
$pageDE = $this->getDoctrine()
->getRepository('MySitePublicBundle:Page')
->findOneBy(array('idName' => 'about', 'lang' => 'DE'));
if (!$pageDE) {
throw $this->createNotFoundException('About page (DE) not found.');
}
if (!$pageEN) {
throw $this->createNotFoundException('About page (EN) not found.');
}
$formDE = $this->createFormBuilder($pageDE)
->add('title', 'text')
->add('content', 'text')
->getForm();
$formEN = $this->createFormBuilder($pageEN)
->add('title', 'text')
->add('content', 'text')
->getForm();
//Save Form here
return $this->render('MySitePublicBundle:Admin:about.html.twig', array(
'aboutPageDE' => $pageDE, 'aboutPageEN' => $pageEN, 'formDE' => $formDE->createView(), 'formEN' => $formEN->createView(),
));
}
My Question is: How to save the form that has been used out of one controller?
Based on the Forms and Doctrine section of the Symfony2 Docs (or in your case, since you're not using a Form class) --
So where you have //save form here assuming you've set up MySitePublicBundle:Page to save the Title and Content (and has the normal getters/setters).
if ($request->getMethod() == 'POST') {
$form->bindRequest($request);
// data is an array with "title" and "content" keys
$data = $form->getData();
// You'll need to have some switch depending on which language you're dealing
// with... (unless its both, then just repeat for $pageDE)
$pageEn->setTitle($data['title']);
$pageEn->setContent($data['content']);
$em = $this->getDoctrine()->getEntityManager();
$em->persist($pageEn);
$em->flush();
}
In your controller you could test if the request contains the forms, such as:
if($this->getRequest()->get('form1')) {
//
} elseif($this->getRequest()->get('form2')) {
//
}