I have 2 tables that have a many to many relation ship
Members: id, name , ...
Locations: id,location_id
Connected by a pivot table
members_location: member_id, location_id
in my Location model I have the following function
public function members(){
return $this->belongsToMany('App\Member','location_member','location_id','member_id');
}
LocationController.php Passes data to the blade template
$locations = Location::All();
return view('locations.overview',['locations' => $locations]);
So in my overview.blade.php i do the following
#include('includes.message-block')
<!-- get a list of locations -->
<table class="member_overview table table-striped table-hover">
<thead>
<tr>
<th>Naam</th>
<th>Locatie</th>
<th>Opmerking</th>
</tr>
</thead>
<tbody>
#foreach($locations as $location)
<tr>
<td>
{{$location->location_id}}
</td>
<td>
{{$location->members->id}}
</td>
<td>
</td>
</tr>
#endforeach
Which returns an error.
Undefined property: Illuminate\Database\Eloquent\Collection::$id (View: ...)
If i drop id property on:
<td>
{{$location->members->id}}
</td>
I get an array [{"id":1,"first_name":"Sa ..}]. how can I select the first_name property from that array
tinker output when selecting one location
$location->members
=> Illuminate\Database\Eloquent\Collection {#658
all: [
App\Member {#664
id: 1,
the belongsToMany relationship will return a collect not a single instance of an eloquent object.
To overcome this issue you will either have loop through the members e.g.
foreach($location->members as $member) ...
of if you just want the first one then you could do:
$location->members->first()->id
Also, just an FYI but you're going to end up with a potentially large number of DB calls due to the n+1 issue that comes with many-to-many relationships. To overcome this you can simple add a with method in your controller i.e.
$locations = Location::with('members')->get();
NB you must use get and not all (like above) if you have any other methods in the chain.
Hope this helps!
Related
I'm Working with Asp .net MVC3.I'm displaying a table in front end.I'm using a stored procedure to populate the table table columns will be populated dynamically.For example i have contains id,name,chk1,chk2,chk3 columns the stored procedure populates table where columns of the table will be populated dynamically.how can i handle this situation in view page.
following is my view ,
<table>
<tr>
#foreach (var item in Model.colName)
{
<th>#item.column_name</th>
}
</tr>
#foreach (var item in Model.bgv)
{
<tr>
<td>#item.id</td>
<td>#item.name</td>
<td>#Html.DropDownList("ddlchk", new SelectList (Model.dd, "Validation_Code", "Validation_Status","Validation_Status"))</td>
<td>#Html.DropDownList("ddlchk", new SelectList(Model.dd, "Validation_Code", "Validation_Status","Validation_Status"))</td>
<td>#Html.DropDownList("ddlchk", new SelectList(Model.dd, "Validation_Code", "Validation_Status","Validation_Status"))</td>
</tr>
}
</table>
This works correct when stored procedure return value for all(id,name,chk1,chk2,chk3) the columns.when SP returns id,name,chk1,chk2 columns it shows td with no header?how i can handile this situation?
Try this:
<thead>
<tr>
#foreach (var item in Model.colName)
{
<th>#item.column_name</th>
}
</tr>
</thead>
I am trying to send to the view an IEnumerable and to show every element in it but I have a problem when I send it. It says that:
{System.Linq.Enumerable.WhereSelectEnumerableIterator<System.Linq.IGrouping<string,MvcApplication4.Models.USER>,<>f__AnonymousType8<string,int>>}
and I dont know how to handle it.
This is my view :
#model IEnumerable<dynamic>
I get dynamic because i go to this view from couple of functions how send different types.
<table border="1" style="text-align:center">
<tr>
<td> </td>
<td> user name </td>
<td>age </td>
<td>comments </td>
</tr>
#foreach (var t in (Model))
{
<tr>
<td>#(count++))</td>
<td> #Console.WriteLine(t)</td>
<td> </td>
<td> </td>
</tr>
}
</table>
I get the IEnumerable from this linq :
var allU = (from m in comList
join c in users on m.user equals c.user into cm1
from cm2 in cm1.DefaultIfEmpty()
group cm2 by m.user into grouped
select new { name = grouped.Key, count = grouped.Count() }).AsEnumerable();
So my question is really : how can I get the elements of it in the view?
You can't reference the type in your view because it is an anonymous type. Instead, define a type to store the results of your query:
public class Result
{
public string Name { get; set; }
public int Count { get; set; }
}
Then change your query to project into that type:
var allU = (from m in comList
join c in users on m.user equals c.user into cm1
from cm2 in cm1.DefaultIfEmpty()
group cm2 by m.user into grouped
select new Result { Name = grouped.Key, Count = grouped.Count() }).AsEnumerable();
Then you'll be able to bind to the type IEnumerable<Result> in your view.
I have a Model containing many rows. One of the columns in the row shows the datastore location. What I would like to do is to have a table of data for each datastore location. Is there some simple way I could do this with Razor? Here's a simplified example of what I have.
<table>
#foreach (var item in Model) {
<tr>
<td>#item.Datastore</td>
<td>#item.xxx</td>
<td>#item.yyy</td>
</tr>
}
</table>
If you haven't got the list of individual data sources available to you in your model you will have to extract them directly from you model. You can do this using Linq and using the Distinct method to find the unique values.
Once you have those you can then loop through the list and create individual table for each data store and populate them using filtered values from your model based on the data store value.
Something like this should work:
#{
var dataStores = Model.Select(i => i.DataStore).Distict();
foreach(var dataStore in dataStores) {
<table>
#foreach (var item in Model.Where(i => i.DataStore == dataStore)) {
<tr>
<td>#item.Datastore</td>
<td>#item.xxx</td>
<td>#item.yyy</td>
</tr>
}
</table>
}
}
I know this sound somewhat off-piste but how would you create a weakly typed view where you pass in a collection of objects and iterate in razor accordingly and display in a table?
-- Controller View --
???
-- Razor View ---
#foreach (var item in Model)
{
<tr>
<td>
#item.attr1
</td>
<td>
#item.attr2
</td>
</tr>
}
Frist you know the data send
From Controller -------> view by two way
By weak type view
and by strong type view
there is no other way of passing data from controller to view ...(remember)
what is intelliscence ----> which show the related sub property of any model
like we write Model. --------> then all property show in
droupdown list after dot(.).
A.what is weak type view
This is used without using model i.e like using ViewBag and other.
There is no intellisence for this type of view and it is complicated, and when you write
any name which not exist then it give at runtime error.
Ex.
.............Controller
ViewBag.List = List<job>;
return View();
.............Razor View
#foreach(var item in ViewBag.List)
{
// when you write no intellisence and you want to write your own correct one...
#item.
}
B. What strongly type view
this is used model to send data from controller to view an vice-versa.
Model are strongly typed to view so, it show intellicence and when you write wrong
then there only error show at compile time..
Ex.
.................Controller
List<job> jobdata =new List<job>();
return View(jobdata);
................view
//Mention here datatype that you want to strongly type using **#model**
#model List<job>
#foreach(var item in Model)
//this **Model** represent the model that passed from controller
// default you not change
{
#item. //then intellisence is come and no need write own ....
}
that is weak and strong type view ......
So now you solve any problem with this basic.....
may I hope it help u....
But it is best to use Strongly Typed view so it become easy
to use and best compare to weak...
#model dynamic
Will do what you want, I believe.
If its going to be a collection, then maybe use
#model ICollection
It's not weakly typed. It's typed to a collection of some kind.
#model IEnumerable<MyClass>
OK, late to the party I know, but what you're after is a view stating "#model dynamic" as already stated.
Working Example: (in mvc3 at time of posting)
NB In my case below, the view is actually being passed a System.Collections.IEnumerable
As it's weakly typed, you will not get intelesense for the items such as #item.Category etc..
#model dynamic
#using (Html.BeginForm())
{
<table class="tableRowHover">
<thead>
<tr>
<th>Row</th>
<th>Category</th>
<th>Description</th>
<th>Sales Price</th>
</tr>
</thead>
#{int counter = 1;}
#foreach (var item in Model)
{
<tbody>
<tr>
<td>
#Html.Raw(counter.ToString())
</td>
<td>
#item.Category
</td>
<td>
#item.Description
</td>
<td>
#item.Price
</td>
</tr>
#{ counter = counter +1;}
</tbody>
}
</table>
}
Edit: removed some css
I've got a model that is returning a IEnumerable of football picks for a variable number of users. Due to this, I'm dynamically building an html table with a variable number of columns. Basically, my picks will come back like this. However, each game is going to be repeated for each User, so I'm only adding the first 3 columns of each table row once, and then adding only a single tag until the gameID changes. I know there are probably better ways to do this, but it's just a side project that I need to get done quickly. And, I just want to figure out why it's not working.
GameID
GameDateTimeDisplay
GameTeamDisplay
WinningTeamDisplay
PickedTeamAbbr
OK, so here is the insanity that doesn't work. I can get my table headers created successfully, but then the tbody isn't working, but it's erroring in an odd place.
I had to put all the #Html.Raw(...) stuff in there because it was having trouble finding the end tags for the foreach and if statements without them.
Anyway, here is my code. The line that is causing the exception is this:
#gameID = #pick.Game.GameID;
The exception is --> Compiler Error Message: CS1525: Invalid expression term '='
The intellisense shows #gameID as a variable and the #pick.Game.GameID seems to be correct as well.
<table>
<thead>
<tr>
<th>Game</th>
<th>Game Date/Time</th>
<th>Winner</th>
#foreach(var name in #Model.UserNames) {
<th>#name</th>
}
</tr>
</thead>
<tbody>
#{
int lastGameID = 0;
int gameID = 0;
bool firstGame = true;
}
#foreach(var pick in #Model.Picks) {
#gameID = #pick.Game.GameID;
if(#gameID != #lastGameID) {
if(!#firstGame){
<text>#Html.Raw("</tr>")</text>
}
#Html.Raw(
<tr>
<td>#pick.GameTeamDisplay</td>
<td>#pick.GameDateTimeDisplay</td>
<td>#pick.Game.WinningTeam.TeamAbbr</td>
<td>#pick.PickedTeamAbbr</td>
)
}
else {
#Html.Raw(<td>#pick.PickedTeamAbbr</td>)
}
}
#Html.Raw(</tr>)
</tbody>
</table>
UPDATE:
I've removed the #Html.Raw, , etc... Also wrapped the gameID assignment in a #{}. It's now giving me an error on this line,
#{gameID = #pick.Game.GameID;}
Compilation Error: CS1501: No overload for method 'Write' takes 0 arguments
Here is the updated Code:
#foreach(var pick in #Model.Picks) {
#{gameID = #pick.Game.GameID;}
if(#gameID != #lastGameID) {
if(!#firstGame){
#:</tr>
}
#:<tr>
<td>#pick.GameTeamDisplay</td>
<td>#pick.GameDateTimeDisplay</td>
<td>#pick.Game.WinningTeam.TeamAbbr</td>
<td>#pick.PickedTeamAbbr</td>
}
else {
<td>#pick.PickedTeamAbbr</td>
}
}
</tr>
You need to surround it with { } to make it a codeblock
#{gameID = pick.Game.GameID;}
Also, you don't need the # inside the foreach/if statements because they're code blocks.
e.g. you could just write:
foreach(var name in Model.UserNames) {
Just write
#foreach(var pick in Model.Picks) {
<tr>
<td>#pick.GameTeamDisplay</td>
<td>#pick.GameDateTimeDisplay</td>
<td>#pick.Game.WinningTeam.TeamAbbr</td>
<td>#pick.PickedTeamAbbr</td>
</tr>
}
You don't need # inside code block. You can use #: instead of <text>, Html.Raw
You can see here Razor syntax reference
I determined that my Razor view code was simply too complex. The real problem was that I was trying to force a view to work with a Model that I had created for another view. I ended up creating a few more models specifically for this view. Code is much cleaner and best of all it works! Here is the code I ended up with.
<table>
<thead>
<tr>
<th>Game</th>
<th>Game Date/Time</th>
<th>Winner</th>
#foreach(var name in #Model.UserNames) {
<th>#name</th>
}
</tr>
</thead>
<tbody>
#foreach(var game in #Model.Games) {
<tr>
<td>#game.GameDescription</td>
<td>#game.GameDisplayDateTime</td>
<td>#game.GameWinner</td>
#foreach(var pick in game.GamePicks){
<td>#pick.PlayerPick</td>
}
</tr>
}
</tbody>
</table>