Laravel parent-child data displaying in Bootstrap table in blade - php

I have a simple Laravel project to show parent records in a table, with collapsible row(s) to show child records. I have a nice Bootstrap table, can join the parent and child tables in my controller and populate the table, but can't group the children under the one parent. I'm not sure if I built the passed dataset incorrectly in my controller, or if I'm missing some "Laravel way" to do this. It's an easy proposition, loop through the parents until one has a child, then loop through it's children, then resume looping parents, etc., but it's driving me insane. I can't find any direct example or reference to solve my issue, but this is a common requirement.
I need to know how to reference the child records to loop through them to populate the collapsed section. My attempts either result in a parent row for each individual child (the code shown) or a bunch of duplicated child items. If I could pass two datasets from my controller, one of parents and a separate of children, then I could in code build this, but I don't know how to do that in Laravel or if there's an easier way.
I did start with Laravel DataTables but to get detail child rows requires implementing handlebar templates in Laravel and I couldn't find a usable reference to do that, so decided to revert to from-scratch-code my own using a Bootstrap table. Than I got stuck.
Here's my controller (DataassetsController.php). The "investment-accounts" table contains parents (as do the other joined tables), and the "investment-line-items" table contains child records for the "investment-accounts".
class DataassetsController extends Controller
{
public function getUnion()
{
$money = DB::table('monetary_assets')
->select(['monetary_asset_name as name', 'monetary_asset_type as type', 'monetary_asset_value as value', DB::raw("NULL as item"), DB::raw("NULL as institution_id"), DB::raw("NULL as item_id")]);
$personal = DB::table('personal_property_assets')
->select(['personal_name as name', 'personal_type as type', 'personal_current_value as value', DB::raw("NULL as item"), DB::raw("NULL as institution_id"), DB::raw("NULL as item_id")]);
$investments = DB::table('investment_accounts')
->join('investment_line_items', 'investment_institution_name_id', '=', 'investment_accounts.id')
->select(['investment_institution_name as name', 'Investment_account_type as type', DB::raw("NULL as value"), 'investment_name as item', 'investment_institution_name_id as institution_id', 'investment_accounts.id as item_id' ]);
$union = DB::table('real_property_assets')
->select(['real_name as name', 'real_type as type', 'real_current_value as value', DB::raw("NULL as item"), DB::raw("NULL as institution_id"), DB::raw("NULL as item_id")])
->union($money)
->union($personal)
->union($investments)
->get();
return view('assets.allassets', ['user_assets' => $union]);
}
Here's my route:
Route::get('/dataassets', 'DataassetsController#getUnion');
Here's my blade (allassets.blade.php) code:
#extends('layouts.master')
<!-- Collapsible accordion rows in bootstrap -->
<div class="col-lg-6">
<div class="panel panel-default">
<div class="panel-heading"><h3>All Assets</h3></div>
<div class="panel-body">
<table class="table table-condensed" style="border-collapse:collapse;">
<thead>
<tr><th> </th>
<th>Asset Name</th>
<th>Type</th>
<th>Value</th>
</tr>
</thead>
<tbody>
#foreach ($user_assets as $user_asset) <!-- don't forget to add a variable to the loop to index ID's of subrow -->
<tr data-toggle="collapse" data-target="#demo{{$loop->index}}" class="accordion-toggle">
#isset($user_asset->item)
<td><button class="btn btn-default btn-xs"><span class="glyphicon glyphicon-eye-open"></span></button></td>
#else
<td></td>
#endisset
<td>{{$user_asset->name}}</td>
<td>{{$user_asset->type}}</td>
<td style="text-align:right">${{ number_format($user_asset->value,2)}}</td>
<?php $var = ($user_asset->name); ?>
</tr>
#isset($user_asset->item)
<tr>
<td colspan="12" class="hiddenRow"><div class="accordian-body collapse" id="demo{{$loop->index}}">
<table class="table table-striped">
<thead>
<th>Item</th>
<th>Value</th>
<th>Institution</th>
<th>Item</th>
<th>Edit</th>
</thead>
<tbody>
<tr>
<td>{{$user_asset->item}}</td>
<td> placeholder</td>
<td> {{$user_asset->institution_id}}</td>
<td> {{$user_asset->item_id}}</td>
<td><a href="#" class="btn btn-default btn-sm">
<i class="glyphicon glyphicon-cog"></i></a></td></tr>
</tbody>
</table>
</div> </td>
</tr>
#endisset
#endforeach
</tbody>
</table>
</div>
</div>
</div>
<!-- end Bootstrap table -->
Here's a picture of what I get, with one of the children rows popped out:
Bootstrap table showing only one child at a time with multiple copies of parent
Here's a pic of the database tables in question:
The parent and child tables (other tables referenced above do not have children, only this one)
I'm using Laravel 5.5 & PHP7 on XAMPP
Any help or suggestions are very welcome.

Related

Can't delete from SQLite table in Laravel

I'm Doing a "take home assignment" for job interview. While I have some experience in web development, its not my forte. I am trying to delete a row in a SQLite table using a HTML DELETE button. I am using Laravel-php framework.
I've tried different solutions on google and stack Overflow, but none seem to solve the problem. I modeled my approach after this Laracasts video
Link to my code
The blade seems to be passing the correct info ($id from $contact->id) & the controller seems to be receiving. But the given contact associated with the id isn't being deleted.
FROM BLADE:
<div class="col-md-6">
<table class="table table-striped table-hover">
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Address</th>
</tr>
#foreach($contacts as $contact)
<tr>
<td> {{$contact->f_name}} </td>
<td> {{$contact->l_name}} </td>
<td> {{$contact->address}} </td>
<td>
<form method="POST" action="/delete/{{ $contact->id }}">
#method('DELETE')
#csrf
<div class="field">
<div class="control">
<button type="submit" class="button">Delete Contact</button>
</div>
</div>
</form>
</td>
</tr>
#endforeach
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</table>
</div>
FROM CONTROLLER:
public function delete($id) {
Contact::find($id)->delete();
return view('index');
}
FROM ROUTE:
Route::delete('/delete', [
'uses'=>'ContactController#delete',
'as'=>'contacts.delete'
]);
you're not getting the id on your delete method, you need to include it on the url like
Route::delete('/delete/{id}', [
'uses'=>'ContactController#delete',
'as'=>'contacts.delete'
]);
in this case, you don't need to change the delete method.
you can also retrieve the id from the request object without changing the delete route, int this case you need to include the id as a hidden input on your view and your delete method will look like this
public function delete(Request $request) {
Contact::find($request->id)->delete();
return view('index');
}

Laravel one click sorting

I'm new on this Laravel and was trying to play around the Laravel's quickstart project. I'm not familiar with the variable set within the template. I'm trying to create a one button/link to sort by ascending or decending all the retrieved records.
Usually I have no problem with basic PHP sorting by using switch (), but since I'm using Laravel, things are getting a little bit unfamiliar to me. So here's the code:-
routes.php
Route::group(['middleware' => ['web']], function () {
Route::get('/sort/{id}', function ($id) { // get to the sorted page ("/sort")
switch ($id) {
case 'asc' :
return view('tasks', [ // get the tasks table from the database
'tasks' => Task::orderBy('name', 'asc')->get(),
'sort' => "desc"
// From the tasks table, get the listing from the table and arrange them descending by date of creation
]);
case 'desc' :
return view('tasks', [ // get the tasks table from the database
'tasks' => Task::orderBy('name', 'asc')->get(),
'sort' => "asc" // From the tasks table, get the listing from the table and arrange them ascending by date of creation
]);
}
});
tasks.blade.php
<div class="panel-body">
<table class="table table-striped task-table">
<thead>
<th>Task</th>
<th> </th>
</thead>
<tbody>
#foreach ($tasks as $task) <!-- display the listings from the tasks table -->
<tr>
<td class="table-text"><div>{{ $task->name }}</div></td>
<td class="table-text"><div>{{ $task->description }}</div></td>
<!-- Task Delete Button -->
<td>
<form action="{{ url('task/'.$task->id) }}" method="POST"> <!-- form action select the id on the task table database($task->id) -->
{{ csrf_field() }}
{{ method_field('DELETE') }} <!-- delete the field -->
<button type="submit" class="btn btn-danger">
<i class="fa fa-btn fa-trash"></i>Delete
</button>
</form>
</td>
</tr>
#endforeach
</tbody>
</table>
</div>
I just refer some of the codes on the internet and make some of my own as I'm not used with the variable within the HTML part in Laravel. I thought it would work but when I run the code, it throws the undefined variable: sort in the tasks.blade.php. Usually any variable is within the backend PHP, but this is a whole new environment to me. So, I wonder how does variable in HTML works? and how to make the sort working?
EDIT 1:
Screenshot of error:-
Your sort doesn't work, because you sort Task model ascending in both cases. You should use
Task::orderBy('name', 'desc')->get()
in second case. About variable it would be more clear if you provide screenshot.
I have found a solution for my own question. Instead of using {{$sort}} in the tasks.blade.php which I haven't set any default key, I need to use isset() function to check whether the variable is set accordingly or not. Since Laravel have its own function for that, I just use them:-
{{{ isset($sort) ? $sort : 'asc' }}}
This mean that it will set the default initial $sort variable into ascending (asc).
That's the answer for it. Thank you, me!

Dynamic buttons href tests with phpunit

I'm initiating my tests using phpunit so, I have doubts about how to test things dynamically. I created a table dynamically as the image bellow
Here are my view:
<div class="panel-body">
#if(Session::has('success'))
<div class="alert alert-success">{{Session::get('success')}}</div>
#endif
<table class="table">
<th>Unity Name</th>
<th>Phone Number</th>
<th>Actions</th>
<tbody>
#foreach($companies as $company)
<tr>
<td>{{$company->name}}</td>
<td>{{$company->owner_number}}</td>
<td>
{{Form::open(['method' => 'DELETE', 'url'=>'/admin/company/'.$company->id, 'style' => 'display:inline'])}}
<button type="submit" class="btn btn-default fa fa-trash-o"></button>
{{Form::close()}}
</td>
</tr>
#endforeach
</tbody>
</table>
</div>
</div>
So, how can I test the href tag if I haven't previously the tag id?
I did some tests like these one in Symfony projects.
In dev environment, I insert some data in a dev database. After this step, I launch functionnal tests. In these tests, I analyze tag's content. Here is an example from your data :
$client = static::createClient();
$crawler = $client->request('GET', '/yourUrl');
$node = $crawler->filter('#show-company-1');
self::assertNotEmpty($node, "Node #show-company-1 does not exists");
self::assertEmpty( $node->html(), "#show-company-1 content is not empty");
self::assertContains('/admin/company/1', $node->attr('href'), "a#show-company-1.href has not a good value");
Before request, you can add some logic to determine the id of your company.

Laravel 5.2: Can variable be classified in view?

I am using Laravel 5.2.
My question is:
Can variable be classified in view?
For example:
There is a controller ,it can get all of the articles belonging to the current user, like this:
public function index()
{
$user=\Auth::user();
$articles = $user->articles;
return view('user.dashboard.index', compact('articles'));
}
In view,these codes below can show the articles,like this:
<div class="card">
<div class="card-header">
Articles
</div>
#if ($articles!=null)
<table class="table table-sm">
<thead>
<tr>
<th>title</th>
<th>created time</th>
<th>status</th>
</tr>
</thead>
<tbody>
#foreach ($articles as $article)
<tr>
<td>{{$article->title}}</td>
<td>{{$article->created_at}}</td>
<td>{{$article->status}}</td>
</tr>
#endforeach
</tbody>
</table>
#else
<p>Nothing</p>
#endif
</div>
These articles can be classified into two types:
1、“published”,status is 1.
2、“unpublished”,status is 0.
Question:
I would want the published articles to be shown in a card(div class="card"), and, the unpublished articles to be shown in another card.
Can they be classified in view? Thus,it doesn't need to query twice.
Try to use collection method where()
#foreach ($articles->where('published', 1)->all() as $article)
Just change published and 1 to real ones.

Wordpress,Custom Theme,Custom Post Type

I'm beginner in web developing. I'm creating sites in WordPress with Custom theme (underscore.me). I need to make two tables in the site. First table is "past projects", the second one is "Future project".
I created the custom post type for this table:call(Properties),
Custom post type "Properties" show up:
1.Past project or Future Project
2.Property Name
3.Property Photo
4.Property Address
5.Property Date
6.Property apts
7.Property Size
8.Property Status
9...
This is my HTML for this tables:
<div id="main-content">
<div class="container">
<div class="sixteen columns">
<div class="tab-content sixteen columns">
<div class="tab-pane active" id="table1">
<p class="table-name">Featured Projects</p>
<table class="footable tablet footable-loaded">
<thead>
<tr>
<th data-class="expand" data-sort-initial="true" class="footable-sortable footable-sorted footable-first-column">
<span title="table sorted by the column on load">Project</span>
<span class="footable-sort-indicator"></span>
</th>
<th class="footable-sortable">
<span title="sorting disabled on this column">Photos</span>
<span class="footable-sort-indecator"></span>
</th>
<th class="footable-sortable">
Address
<span class="footable-sort-indecator"></span>
</th>
<th data-hide="phone" data-type="numeric" class="footable-sortable">
Year
<span class="footable-sort-indecator"></span>
</th>
<th data-hide="phone" data-type="numeric" class="footable-sortable">
APTS
<span class="footable-sort-indecator"></span>
</th>
<th data-hide="phone" data-type="numeric" class="footable-sortable">
SQ. FT
<span class="footable-sort-indecator"></span>
</th>
<th data-hide="phone" data-type="numeric" class="footable-sortable">
STATUS
<span class="footable-sort-indecator"></span>
</th>
</tr>
</thead>
<tbody>
<tr>
<td class="expand footable-first-column">
</td>
<td>
<a class="photo-icon" href="">Photo</a>
</td>
<td>21-45 45th Drive-Long Island City</td>
<td>2010</td>
<td>23</td>
<td>30,000</td>
<td class="footable-last-column">In Development</td>
</tr>
<tr>
<td class="expand footable-first-column">
The Industry
</td>
<td>
<a class="photo-icon" href="">Photo</a>
</td>
<td>21-45 45th Drive-Long Island City</td>
<td>2010</td>
<td>23</td>
<td>30,000</td>
<td class="footable-last-column">In Development</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
Question: How to display posts from a specific post type(custom post type)using php queries in my custom theme page, and how to make the function with PHP queries to easily create or delete "past projects" or "future projects".
I would be so appreciated, if anybody can help me. Thank you again.
Your making it more difficult on your self. You don't need to create any additional database tables unless you really really want to...
This is not what happens when site visitor clicks on a link to view custom post types. (Pseudo Code)
select * from wp_customPostType
Its something like this:
select * from wp_posts where posts.post_type = 'custom_post_type'
This is how you do it. (The order you do it in makes no difference)
Use this post type generator to create your custom post type but only make one called Projects (it's DRYer) and enable
taxonomies.
In your theme directory copy single.php, paste it and change the
name to single-Projects.php.
In your theme's functions.php (you should actually be using a child
theme if you're not already) register the new post type with ?php
register_post_type( $post_type, $args ) ?>
In single.php (the orignal, not the one you copied) add something like this:
if ( 'Project' == get_post_type() )
{
use single-Project.php
}
else
{
continue using this page (single.php)
You will have to create the new layout for single-Project.php but then all you have to do is add a taxonomy for past and future to the Projects that you create. When the future becomes the past all you have to do is change the taxonomy rather than make a new post for past projects.

Categories