in new to laravel and Im trying to set up an edit blade using resource controller . ( using laravel 5.7) but it is throwing an error like this
Missing required parameters for [Route: home.hotels.update] [URI: home/hotels/{hotel}]. (View: C:\xamp\....\.....\edit.blade.php)
Please note:
when i hover over edit button it is correctly pointing to the id's and
when i tries to echo a fieldname inside my "edit function"in controller it returns the correct page but "blank" . can some one tell me wher this error comming from and if possible how to fix this
code in my index blade ( part relating to the edit)
#foreach($hotels as $c)
<tr>
<td>{{$c->hotelid}}</td>
<td>{{$c->hotelname}}</td>
<td>{{$c->city}}</td>
<td>{{$c->location}}</td>
<td>{{$c->singleroom}}</td>
<td>{{$c->doubleroom}}</td>
<td>{{$c->deluxroom}}</td>
<td>{{$c->deluxdouble}}</td>
<td>{{$c->superiorsuit}}</td>
<td><a href="{{route('home.hotels.edit',$c->id)}}"class="btn btn-info" >Update </a>
my edit blade
im passing the entries like this
<form method="post" action="{{route('home.hotels.update',$hotels->id)}}">
#csrf
{{ method_field('PUT') }}
<div class="form-group">
<div class="row">
<label class="col-md-6">Hotel ID</label>
<div class="col-md-6"><input type="text" name="hotelid" class="form-control" value="{{$hotels->hotelid}}"> </div>
</div>
......... rest of the input fields follows........
controller functions
public function index()
{
$arr['hotels']=hotels::all();
return view('admin.hotels.index')->with($arr);
}
my update function also has the same code as store ------
public function store(Request $request, hotels $hotels)
{
$hotels->hotelid=$request->hotelid;
$hotels->hotelname=$request->hotelname;
...........other fields..................
$hotels->save();
return redirect('home/hotels');
}
public function edit(hotels $hotels )
{
$arr['hotels'] = $hotels;
return view('admin.hotels.edit')->with($arr);
}
and my routes
Route::get('/home', 'HomeController#index')->name('home');
Route::resource('home/users', 'Admin\UsersController',['as'=>'home']);
Route::resource('home/hotels', 'Admin\HotelsController',['as'=>'home']);
Related
I have some quotes in a database and am trying to use Laravel to display it on a page. I have the quotes being pulled from the controller then passed to the view but I am getting an error:
Undefined variable: quotes (View: C:\laragon\www\resources\views\inc\quote.blade.php) (View: C:\laragon\www\\resources\views\inc\quote.blade.php) (View: C:\laragon\www\\resources\views\inc\quote.blade.php
QuotesController.php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
class QuotesController extends Controller
{
public function index()
{
$quotes = DB::table('quotes')->get();
return view('inc.quote', ['quotes' => $quotes]);
}
}
quote.blade.php
<div id="MarketingQuote" class="container-fluid padding bg-light">
<div class="row">
<div class="col-lg-6">
<h2>Marketing Quote of the day</h2>
#foreach($quotes->all() as $quote)
<li>{{$quote}}</li>
#endforeach
<br>
</div>
<div class="col-lg-6">
<img src="img/computer.jpg" class="image-fluid" alt="">
</div>
</div>
</div>
Migration Table for Quotes
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateQuotesTable extends Migration
{
public function up()
{
Schema::create('quotes', function (Blueprint $table) {
$table->bigIncrements('id');
$table->text('quote');
$table->string('author');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('quotes');
}
}
Why do I get this error? And how do I get only one quote to display at a time and only change upon each page refresh?
Thank you.
I advise you to input the variable $quotes in the controller, And I remember the passed variable array key which can use and not have to use all function.
The below code from laravel manual:
Route::get('greeting', function () {
return view('welcome', ['name' => 'Samantha']);
});
Hello, {{ $name }}.
change
#foreach($quotes->all() as $quote)
<li>{{$quote}}</li>
#endforeach
into
#foreach($quotes as $quote)
<li>{{$quote}}</li>
#endforeach
I have a Spring MVC application using Thymeleaf for templating. I am using enums to generate checkboxes dynamically. So if my enum file has 3 values it will generate 3 checkboxes:
My enum file:
public enum Foods {
PIZZA("Pizza"),
PASTA("Pasta"),
MAC_CHEESE("Mac and Cheese"),
ICE_CREAM("Ice Cream"),
BURGER("Burger"),
private String type;
Foods(String type) {
this.type = type;
}
public String getType() {
return this.type;
}
}
This is my checkbox generation:
<label for="decision">What is your favorite food?</label>
<div id="decision" class="row" style="margin-top:1%;">
<div class="col-md-4" th:each="option : ${T(in.app.model.enums.Foods).values()}">
<div class="checkbox checkbox-custom checkbox-circle">
<input name="decision" type="checkbox" th:id="${option.toString()}" th:value="${option}" />
<label th:for="${option.toString()}" th:text="${option.type}"></label>
</div>
</div>
</div>
This code will generate 5 checkboxes for each of the food type. All works till here. The issue I am facing is how to set the checked attribute when reading a saved record.
I am getting back an object via the model view controller. The object has a food property with its value as the array of the chosen food types.
user = {
.
.
food : ["PIZZA", "BURGER", "PASTA"],
.
.
}
Now I want to loop through this array and if the value match then set the checkbox.
I am trying to do something like this:
<label for="decision">What is your favorite food?</label>
<div id="decision" class="row" style="margin-top:1%;">
<div class="col-md-4" th:each="option : ${T(in.app.model.enums.Foods).values()}">
<div class="checkbox checkbox-custom checkbox-circle">
<input
name="decision"
type="checkbox"
th:id="${option.toString()}"
th:value="${option}"
th:each="food : ${user.food}"
th:attr="checked = ${food} == ${option} ? 'checked'"
/>
<label th:for="${option.toString()}" th:text="${option.type}"></label>
</div>
</div>
</div>
I know its wrong (since its not working) but I am unable to figure out how to loop over two arrays to show the checkboxes and to check them.
You might want to try using th:checked instead of th:attr if you can, so:
th:checked="${food == option.type}"
This post might also be helpful when looking into that. If you can't use th:checked, switching to the below statement should also work.
th:attr="checked=${food == option.type} ? 'checked'"
It also seems like you may run into some issues with checking this data due to case sensitivity while comparing, in which case this post might be helpful.
The safe option is to go with
th:attr
and do compare like #Artichoke
th:attr="checked=${food == option.type} ? 'checked'"
The problem with "th:checked" is, its simply do not go well when you need to post the data unless you change the value. You see its value as null if you do not switch it.
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;
}
How can I pass data from partial view on submit form in ASP.NET MVC.
#using (Html.BeginForm("Edit", "BlogPost", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
................
#Html.Partial("PostImagesForPost",Model.PostImages)
}
PostImagesForPost - partial view:
#model IEnumerable<Blog.Models.PostImage>
<script type="text/javascript" src="~/Scripts/jquery.zoom.min.js"></script>
<div>
#{
List<Blog.Models.PostImage> images = Model.ToList();
<ul class="images">
#foreach (var img in images)
{
string parameterValue_small = "~/BlogPhotos/120/" + img.Photo.ToString();
string parameterValue_big = "~/BlogPhotos/600/" + img.Photo.ToString();
<li>
<div id="jquery-image-zoom-example">
<span data-postid="#img.ID" data-delete="true" class="deletespan"></span>
<a href="#Url.Content(parameterValue_big)">
<img src="#Url.Content(parameterValue_small)" data-postid="#img.ID" class="zm" onclick="$('.jquery-image-zoom img').click()" />
</a>
<input type="checkbox" checked="checked" name="selectedImagesForDelete" style="display:none;" data-postid="#img.ID" value="#img.ID" />
</div>
</li>
}
</ul>
}
On submit function the parameter selectedImagesForDelete is null.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Post post,string[] selectedImagesForDelete)
{...........}
This has nothing to do with the fact you're using a partial, and everything to do with how the modelbinder in MVC works. For iterable posted items, the model binder expects field names in the form of ListProperty[index].ModelProperty. The problem is that the Html.* family of helpers will not create this name properly unless they are passed an indexed value, which you can't achieve with foreach. The solution is to simply use for, instead:
#for (var i = 0; i < images.Count(); i++)
{
Html.EditorFor(m => image[i].SomeProperty)
}
By passing in a value that's indexed (images[i]), the helper recognizes that it needs to add the proper indexed html prefix to the name, so that the modelbinder will understand where to stuff the value when it's posted back.
Though, in your case, you seem to actually just be manually specifying the HTML for the fields, which is fine, but you're responsible at that point for getting the name values right.
I believe your name property needs to have indexes in the name:
Create a index variable called index and increment it after each iteration
<input type="checkbox" name="selectedImagesForDelete[index]" value="2">
Actually it was a problem with the javascript file. The checkboxes were never checked.
<input type="checkbox" name="selectedImagesForDelete" value="#img.ID" />
But I resolved that problem and now everything works like expected.
But thanks for trying to help me. I appreciate it.
I try to validate a simple form. The validation is well executed but the result page doesn't display the errors.
I use velocity to render the page.
I've used as example the PetClinic project from spring website.
Here is my controller when I hit the "post form" button:
#Controller
#RequestMapping("/subscription")
public class SubscriptionController {
#RequestMapping(value = "/newCustomer", method = RequestMethod.POST)
public String processSubmit(#ModelAttribute Customer customer, BindingResult result, SessionStatus status) {
new CustomerValidator().validate(customer, result);
if (result.hasErrors()) {
return "subscription";
}
else {
status.setComplete();
return "redirect:/admin";
}
}
}
When I go in debug, I see the errors. I'm successfully redirected on the subscription page but the errors are not displayed.
My webpage (simplified):
...
#springBind("customer")
#springShowErrors("<br/>" "")
<form class="form-horizontal" method="post" action="#springUrl("/subscription/newCustomer/")">
....
<!-- Button -->
<div class="controls">
<button class="btn btn-primary">#springMessage("website.subscription.signup")</button>
</div>
</form>
...
if you need anything else, don't hesitate to tell me. Thanks for your help! I'm stuck on this since several days.
EDIT :
I finally found the error. It was with the springBind tag. I didn't well understand that you need to bind the field to show the associated error. Here is the fixed code for one field for twitter bootstrap framework.
#springBind("customer.name")
<div class="control-group #if(${status.error})error#end">
<!-- Prepended text-->
<label class="control-label">#springMessage("website.subscription.name")</label>
<div class="controls">
<div class="input-prepend">
<span class="add-on"><i class="icon-user"></i></span>
<input class="input-xlarge"
placeholder="John Doe" id="name" name="name" type="text">
</div>
<p class="help-block">
#springShowErrors("<br/>" "")
</p>
</div>
</div>
springShowErrors(...) will show all the errors associated with the field name of the POJO customer.