Route Model Binding in Relationships - forms

A store has many products is the relationship.
How to create new product, saves store_id and other product details.
The code as below.
Route is
Route::resource('stores.product', 'productcontroller');
i.e. binding model store with product route.
Model Store
class store extends Model
{
public function product()
{
return $this->hasMany(product::class);
}
}
create product View.
<form method="POST" action="/stores/{{$store->id}}/product" enctype="multipart/form-data">
{{ csrf_field() }}
<div class="form-group">
name <input type="text" name="name" />
</div>
productController#store
public function store ( store $store, Request $request )
{
$this->validate($request, [
'name' => 'required|max:255',
'detail' => 'nullable' ,
]);
$product = new product;
$product-> user_id = auth()->id();
$product-> store_id = $store->id;
$product-> name = $request->name;
$product->save();
return redirect('/stores/{{$store->id}}/product');
}
Please explain how route model binding works in relationships.
What should be my create form's method and action?
Where should productController#store return redirect?

First you have to create the inverse relation between stores and products
Like this:
class Store extends Model
{
public function products()
{
return $this->hasMany(Product::class);
}
}
class Product extends Model
{
public function store()
{
return $this->belonsTo(Store::class);
}
}
Second you have to pass all your stores to your create product page:
public function create (){
$storList = Store::all();
return view("createproductview", compact("storList"));
}
In that page you have to show the stores to select one of them, and manage your errors from the validation process:
<form method="POST" action="{ route("product.store") }}" enctype="multipart/form-data">
{{ csrf_field() }}
<div class="form-group {{ ($errors->has('store'))?"has-error":"" }}">
<label for="store">Store</label>
<select class="form-control" name="tipoaudiencia" id="store">
<option value="">Select one option</option>
#foreach($storList as $row)
<option {{ (old("store") == $row->id ? "selected":"") }} value="{{ $row->id }}">{{ $row->name }}</option>
#endforeach
</select>
#if($errors->has('store'))<p class="help-block">{{ $errors->first('store') }}</p>#endif
</div>
<div class="form-group required {{ ($errors->has('name'))?"has-error":"" }}">
<label for="name">Name</label>
<input type="text" class="form-control" id="name" placeholder="name" name="name" value="{{ old('name') }}" autofocus>
#if($errors->has('name'))<p class="help-block">{{ $errors->first('name') }}</p>#endif
</div>
...
</form>
and last the store function:
public function store ( Request $request )
{
$this->validate($request, [
'name' => 'required|max:255',
'store' => 'required'
]);
$product = new Product;
$product->name = $request->name;
$store = Store::find($request->store);
$store->products()->save($product);//this saves the product and manage the relation.
return redirect('/stores/'.$store->id.'/'.$product->id);
}
Hope this help you

Related

Laravel 5: Form fields not in model

I have a model with a field called map_zips and inside that field, I would like to store up to 5 zip codes, comma separated.
I would like to have five different form fields that before getting stored in the database model, I concatenate the values together and store them in the DB in the single column.
How can I create multiple form fields in a view, validate said form fields, perform what needs to be done on said form fields, store them? Beyond that, I think I will also need to split them up when loading up the edit/update page as well.
I guess the simplest way would be to create 5 different columns, one for each zip, but I'd like to learn how to do this to help extend my limited knowledge of Laravel.
In my ReportsController.php my current store method looks like this:
public function store(Request $request) {
$this->validate($request, $this->rules);
$user = Auth::user();
$report = $request->all();
$report['user_id'] = $user->id;
Report::create($report);
return redirect('/reports')->with('status', 'Report created');
}
I don't know if i undertand you question but you can try this:
if you want 5 input fields in your view you can try this, you will see error messages from you validation and a returned message to confirm that the value was stored propperly
#if (count($errors) > 0)
<div class="alert alert-danger">
#foreach ($errors->all() as $error)
<div>{{ $error }}</div>
#endforeach
</div>
#endif
#if(session()->has('message'))
<div class="alert alert-success">
{{ session()->get('message') }}
</div>
#endif
<form action="{{ route("route_to_store_function") }}" method="post">
<input type="text" name="zip1">
<input type="text" name="zip2">
<input type="text" name="zip3">
<input type="text" name="zip4">
<input type="text" name="zip5">
<button type="submit"></button>
</form>
then in your store function, concatenate the fields, save the report and return with a message to the previous page:
public function store(Request $request) {
$this->validate($request, [
'zip1' => 'required',// you can add more validations here
'zip2' => 'required',
'zip3' => 'required',
'zip4' => 'required',
'zip5' => 'required',
]);
$report = new Report();
$report->map_zips = $request->zip1.",".$request->zip2.",".$request->zip3.",".$request->zip4.",".$request->zip5;
$report->save();
return redirect()->back()->with('message', 'The report has been stored succesfully');
}
Then when you want to edit the report you can try this:
public function edit($id) {
$report = Report::find($id)
$zipCodes = explode(",", $report->map_zips);
return view('edit_report_view', compact("report", "zipCodes"));
}
And in you edit view:
<form action="{{ route("route_to_update") }}" method="post">
<input type="hidden" name="id" value="{{ $report->id }}">
<input type="text" name="zip1" value="{{ $zipCodes[0] }}">
<input type="text" name="zip2" value="{{ $zipCodes[1] }}">
<input type="text" name="zip3" value="{{ $zipCodes[2] }}">
<input type="text" name="zip4" value="{{ $zipCodes[3] }}">
<input type="text" name="zip5" value="{{ $zipCodes[4] }}">
<button type="submit"></button>
</form>

MethodNotAllowedHttpException in RouteCollection.php line 218:Trying to submit data

I created a form and I am trying to submit data, but error:
MethodNotAllowedHttpException in RouteCollection.php line 218:
is coming. What to do?
welcome blade:
#extends('layouts.master')
#section('title')
Welcome!!
#endsection
#section('content')
#include('includes.message-block')
<div class="row">
<div class="col-md-6">
<h2>Enter Your Information</h2>
<form action="" method="post">
<div class="form-group" {{$errors -> has('name') ? 'has-error': ''}}>
<label for="name">Name</label>
<input class="form-control" type="text" name="name" id="name" placeholder="Your name">
</div>
<div class="form-group" {{$errors -> has('email') ? 'has-error': ''}}>
<label for="email">Email-Id</label>
<input class="form-control" type="email" name="email" id="email" placeholder="Enter Your Email Id">
</div>
<div class="form-group">
<label for="branch">Branch</label>
<input class="form-control" type="text" name="branch" id="branch" placeholder="Enter Your Branch">
</div>
<div class="form-group">
<label for="course_name">Course Name</label>
<input class="form-control" type="text" name="course_name" id="course_name" placeholder="Enter Your Course">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
<input type="hidden" name="_token" value="{{Session::token()}}">
</form>
</div>
#endsection
Model:
<?php
namespace App;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
class User extends Model implements Authenticatable
{
use \Illuminate\Auth\Authenticatable;
protected $table = 'students';
}
UserController:
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Input;
//use Illuminate\Support\Facades\Flash;
use InvalidConfirmationCodeException;
use Flash;
//use Mail;
use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersstudents;
class UserController extends Controller
{
public function postData(Request $request)
{
$this -> validate($request,[
'email' => 'required|email|unique:students',
'name' => 'required|max:20',
'branch' => 'required|max:10'
'course_name' => 'required|max:10'
]);
$email = $request['email'];
$name = $request['name'];
$branch = $request['branch'];
$course_name = $request['course_name'];
$student = new User();
$student->email =$email;
$student->name = $name;
$student->branch = $branch;
$student->course_name = $course_name;
$student->save();
return redirect()->back();
}
}
Route/web.php:
Route::group(['middleware' => ['web']], function(){
Route::get('/', function () {
return view('welcome');
});
Route::post('/submit_data',[
'uses' => 'UserController#postData',
'as' => 'submit_data'
]);
});
Migration:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateUsersTable extends Migration
{
public function up()
{
Schema::create('students', function (Blueprint $table) {
$table->increments('id');
$table->string('mail')->unique();
$table -> string('name');
$table -> string('branch');
$table -> string('course_name');
$table->rememberToken();
$table->timestamps();
});
}
public function down()
{
Schema::drop('students');
}
}
My migration's name is create_users_table. I don't understnad why this error is coming. It's an easy and simple form.Just a simple form to submit a students data, and save it in database.
You are posting to a get route
In your welcome.blade.php you forgot to set your action, so by default it will try to post to the same page / which is definded as a get route in your routes/web.php. Set the action to /submit_data like so in your welcome.blade.php:
<form action="{{ url('/submit_data') }}" method="post">
<form action="{{ url('submit_data') }}" method="post">
you can also use blade from like this
{{Form::open(array('url'=>'/submit_data','files'=>true,'class'=>'form-horizontal','file'=>'true'))}}

Angular 2 Template Driven Forms - Array Input Elements

I have been struggling for 1 and half day and still couldn't find any solution to the problem. I am working on simple form which has select and checkboxes element.When I try submitting the form I do not get the values of select and checkboxes but rather I just get true in the console.
I am working on template driven form.
<form (ngSubmit)="addSubcontractor(subcontractorForm)" #subcontractorForm="ngForm">
<h5>Type :</h5>
<div class="form-group">
<div *ngFor="let contractor_type of contractor_types;let i = index;" class="pull-left margin-right">
<label htmlFor="{{ contractor_type | lowercase }}">
{{ contractor_type }} :
</label>
<input type="checkbox" name="_contractor_type[{{i}}]" [value]="contractor_type" ngModel>
</div>
<div class="form-group">
<select class="form-control costcodelist" name="_cc_id[]" multiple="true" ngModel>
//When I put ngModel on select I just keep getting error
//TypeError: values.map is not a function
<option *ngFor="let costcode of costcodes" [selected]="costcode.id == -1" [value]="costcode.id">{{ costcode.costcode_description }}</option>
</select>
</div>
</form>
Component Section
export class SubcontractorComponent implements OnInit, OnDestroy {
private contractor_types = ['Subcontractor', 'Supplier', 'Bank', 'Utility'];
constructor(private costcodeService: CostcodeService,
private subcontractorService: SubcontractorService) {
this.subcontractorService.initializeServices();
}
ngOnInit() {
this.costcode_subscription = this.costcodeService.getAll()
.subscribe(
(costcodes) => {
this.costcodes = costcodes;
});
}
addSubcontractor(form: NgForm) {
console.log(form.value);
}
}
When I remove ngModel from select element the code runs fine and When I submit the form I get the following output.
_contractor_type[0]:true
_contractor_type[1]:true
_contractor_type[2]:true
_contractor_type[3]:""
I do not get the checkboxes values as well the selected options from select element.
Your comments and answer will appreciated a lot.
Thanks
Here is a simple selection that i use with my Template driven form.
<form #f="ngForm" (submit)="addOperator(f.valid)" novalidate>
<label>Name</label>
<input [(ngModel)]="operator.name" name="name">
<label >Service</label>
<select #service="ngModel" name="service" [(ngModel)]="operator.service">
<option *ngFor='let service of services' [ngValue]='service'>{{service.name}}</option>
</select>
<label >Enabled</label>
<label>
<input type="checkbox" name="enabled" [(ngModel)]="operator.enabled">
</label>
<button type="submit">Create Operator</button>
</form>
.ts
operator: Operator;
ngOnInit() {
this.operator = <Operator>{}; // // Initialize empty object, type assertion, with this we loose type safety
}
addOperator(isValid: boolean) {
if (isValid) {
this.operatorsService.addOperator(this.operator).then(operator => {
this.goBack();
});
}
}
Also im importing this
import { FormsModule, ReactiveFormsModule } from '#angular/forms';

My form is not populating when there is some validation error in the input data. Laravel Collective

Hope yo are all doing great.
I am using Laravel 5.3 and a package LaravelCollective for form-model binding.
I have subjects array that I want to validate and then store in database if there is no error in the input data.
The following snippets show the partial view of form, other views, rules for validations and controller code.
UserProfile.blade.php
<!-- Panel that Adds the Subject - START -->
<div class="col-md-12">
<div class="panel panel-default" id="add_Subject_panel">
<div class="panel-heading">Add Subject(s):</div>
<div class="panel-body">
{!! Form::open( array('method'=>'post', 'url'=>route('user.store.subject', 1)) ) !!}
#include('user.partials.subjects', ['buttonText'=>'Add Subject(s)'])
{!! Form::close() !!}
</div>
</div>
</div>
<!-- Panel that Adds the Subject - END -->
subjects.blade.php
#if (count($errors) > 0)
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
<div class="subject-list">
<div class="input-group subject-input">
<input type="text" name="name[]" class="form-control" value="" placeholder="Subject" />
<span class="input-group-btn">
<span class="btn btn-default">Primary subject</span>
</span>
</div>
</div>
<div class="text-right">
<br />
<button type="button" class="btn btn-success btn-sm btn-add-subject"><span class="glyphicon glyphicon-plus"></span> Add Subject</button>
</div>
<div class="form-group">
<div class="col-md-6 col-md-offset-4 text-right">
<button type="submit" class="btn btn-primary">
{{ $buttonText }} <i class="fa fa-btn fa-subject"></i>
</button>
</div>
</div>
#push('scripts')
{{-- <script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script> --}}
<script src="{{ asset('scripts/jquery-2.2.4.min.js') }}" type="text/javascript" charset="utf-8" async defer></script>
<script>
$(function()
{
$(document.body).on('click', '.btn-remove-subject', function(){
$(this).closest('.subject-input').remove();
});
$('.btn-add-subject').click(function()
{
var index = $('.subject-input').length + 1;
$('.subject-list').append(''+
'<div class="input-group subject-input" style="margin-top:20px; margin-bottom:20px;">'+
'<input type="text" name="name['+index+']" class="form-control" value="" placeholder="Subject" />'+
'<span class="input-group-btn">'+
'<button class="btn btn-danger btn-remove-subject" type="button"><span class="glyphicon glyphicon-remove"></span></button>'+
'</span>'+
'</div>'
);
});
});
</script>
#endpush
I want to validate all the subjects passed as an array to the controller using a custom created form request. the following is the code for that form request
SubjectRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class SubjectRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
// dd("Rules Area");
foreach($this->request->get('name') as $key => $val)
{
$rules['name.'.$key] = 'required|min:5|max:50';
}
// dd($rules);
return $rules;
}
public function messages()
{
// dd('Message Area. . .');
$messages = [];
foreach($this->request->get('name') as $key => $val)
{
$messages['name.'.$key.'.required'] = ' Subject Name '.$key.'" is required.';
$messages['name.'.$key.'.min'] = ' Subject Name '.$key.'" must be atleast :min characters long.';
$messages['name.'.$key.'.max'] = ' Subject Name '.$key.'" must be less than :max characters.';
}
// dd($messages);
return $messages;
}
}
the following is the code for controller method I am using to store inputted array data to database.
public function storeSubjects(SubjectRequest $request)
{
$data = $request->all();
// save logic
dd($data);
}
Problem:
My form is not populating when there is some validation error in the input data.
After getting validation errors, my input fields are blank.
Problem
In subject.blade.php, your code looks like
<input type="text" name="name[]" class="form-control" value="" placeholder="Subject" />
Your fields are not populating because you have left value attribute blank.
Solution:
Pass the old value to solve your problem.
<input type="text" name="name[]" class="form-control" value="{{old('name[]')}}" placeholder="Subject" />
Use Form Model Binding instead
https://laravelcollective.com/docs/5.3/html#form-model-binding
{{ Form::model($user, [....]) }}
{{ Form::text('firstname', null, [...]) }}
{{ Form::close() }}

How to delete an entity from a template with a list of entities (CRUD)?

Explanation:
I have generated the CRUD of an entity, getting the following default actions:
indexAction(): lists all entities.
showAction($id): finds (by ID) and displays an entity.
deleteAction($id): deletes an entity.
another actions.
So, I have seen I can only delete an entity within the actions that use the param $id (e.g.: showAction($id) ) but I want to delete an entity inside the indexAction template because I save a step to users.
The deleteAction needs a request, an ID and use the POST method.
I was trying to code something like:
<a href="{{ path('entity_delete', { 'id': entity.id }) }}" class="btn">
<img src="{{ asset('bundles/acme/images/delete.png') }}" ... />
</a>
When I execute the action, I get the following error:
No route found for "GET /acme/something/4/delete": Method Not Allowed
(Allow: POST, DELETE)
This response is clear and it's what I expected, so I tried to do something similar but using a form. Something like this:
<form id="formDelete" action="{{ path('entity_delete', { 'id': entity.id }) }}" method="post">
<input type="hidden" name="_method" value="DELETE" />
{{ form_widget(delete_form) }}
<a href="{{ url('entity_delete') }}" class="btn" onclick="document.getElementById('formDelete').submit();">
<img src="{{ asset('bundles/acme/images/delete.png') }}" ... />
</a>
</form>
But the line {{ form_widget(delete_form) }} is a problem because the indexAction() hasn't got any parameter and it needs this code:
$deleteForm = $this->createDeleteForm($id);
return $this->render('AcmeBundle:Demo:index.html.twig', array(
'entities' => $entities,
'delete_form' => $deleteForm->createView(),
));
As you can see, the $id param is mandatory for the method createDeleteForm($id) but I can't get it from indexAction().
Question:
What is the best way to solve this issue?
if you only want to have as much delete buttons as items in your index here's how to easily do it.
In the indexAction, add the following loop and don't forget to pass the parameter to the view.
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('FooBundle:Link')->findAll();
$deleteForms = array();
foreach ($entities as $entity) {
$deleteForms[$entity->getId()] = $this->createDeleteForm($entity->getId())->createView();
}
return array(
'entities' => $entities,
'deleteForms' => $deleteForms,
);
}
Basicaly I just loop over all my entities and create the corresponding delete form using the built-in method generated by the crud, storing each form in an array and passing it to the view.
Then in the view, just add the form already available in the edit.html.twig generated view and edit the form_widget's parameter:
<form action="{{ path('foo_delete', { 'id': entity.id }) }}" method="post">
<input type="hidden" name="_method" value="DELETE" />
{{ form_widget(deleteForms[entity.id]) }}
<button type="submit" class="btn btn-small">
<i class="icon-trash"></i>
{{ 'links.admin.form.delete' | trans({}, 'FooBundle') }}
</button>
</form>