Angular http rxjs/Rx Observable Subscribe data binding not working - rxjs

I am trying to bind the data from PHP API to the client (Angular 2), however, it didn't work as expected. Any idea?
This is the laravel API code below,
return response()-> json('message',200);
This is the Angular 2 service and subscribe as below,
getString(): Observable<string> {
return this._http.get(this.api_misc_url)
.map((response: Response) => <string>response.json())
.catch(this.handleError);
}
This is the subscriber code as below,
public ngOnInit(): void {
this.chartId = `mydash-chart-${MydashChartComponent.currentId++}`;
this.laravelApiService.getString().subscribe(
messageFromLaravelApi => this.MessageFromLaravelApi = <string>messageFromLaravelApi,
error => this.errorMessage = <string>error);
}
This is the UI binding code below,
<div class='panel-heading' >
<h2>Charting </h2>
<td>{{ MessageFromLaravelApi }}</td>
</div>
But, I can see value shown on the console log.

Either use subscribe or async , not both. async takes an observable or promise and renders data .
Either this
this.MessageFromLaravelApi$ = this.laravelApiService.getString();
http :
<tr *ngFor="let message of MessageFromLaravelApi$ | async">
<td>{{ message }}</td>
</tr>
OR
this.laravelApiService.getString()
.subscribe(
messageFromLaravelApi =>
this.MessageFromLaravelApi = messageFromLaravelApi,
error => this.errorMessage = <any>error
);
http
<tr *ngFor="let message of MessageFromLaravelApi">
<td>{{ message }}</td>
</tr>
Updating the same code :
Service code
getString(): Observable<string> {
return this._http.get(this.api_misc_url)
.map((response: Response) => response.json())
.catch(err=> console.error(err));
}
Component Code :
public ngOnInit(): void {
this.chartId = `mydash-chart-${MydashChartComponent.currentId++}`;
this.laravelApiService.getString().subscribe(
messageFromLaravelApi =>
this.MessageFromLaravelApi = messageFromLaravelApi,
error => this.errorMessage = error);
}
HTML
<div class='panel-heading' >
<h2>Charting </h2>
<td>{{ MessageFromLaravelApi }}</td>
</div>

Related

How to get the list of client related through the HasManyThrough relationship

I have these 3 tables:
clients
id - integer
name - string
projects
id - integer
client_id - integer
name - string
tasks
id - integer
project_id - integer
name - string
related through the HasManyThrough relationship.
In the client table I have a column relating to the number of tasks relating to the projects of that specific client.
I want that when I click on the number of tasks, I am redirected to the view of the client related tasks. While when I click it shows me all the tasks, but I want, as already specified, the tasks related to the projects of that specific client.
How can I solve this problem?
VIEW:
<tr>
<th class="id">ID</th>
<th class="">Name</th>
<th class="">Task</th>
</tr>
#foreach ($clients as $client)
<tr>
<td>{{ $client->id }}</td>
<td>{{ $client->name }}</td>
<td>
<a href="{{route('task.index'}" class="link-primary">{{
$client->tasks_count }}
</a>
</td>
#endforeach
TaskController:
public function index()
{
$tasks = Task::all();
//dd($tasks);
return view('task.index', compact('tasks'));
}
Create new route:
Route::get('/client/{client}/tasks', ['as' => 'client.tasks', 'uses' => 'ClientController#tasks'])->name('client.tasks');
Add something like this to your view:
//Not sure if that is a right syntax to bind the id in the route, need to verify
<a href="{{ route('client.tasks', [$client->id]) }}" class="link-primary">
{{ $client->tasks_count }}
</a>
Or:
//Route
Route::get('/client/{client}/tasks', [ClientController::class, 'tasks'])->name('client.tasks');
//and view
<a href="{{ URL::to('/client/' . $client->id . '/tasks') }}" class="link-primary">
{{ $client->tasks_count }}
</a>
And controller:
public function tasks(Client $client)
{
$tasks = $client->tasks;
//return your view with tasks associated with this client
}
As you have written
$tasks = Task::all();
All tasks!
You need to pass along the id of the client with the request, preferably with route model binding so that you get a client instance in the controller. Then you can load the tasks or the projects with tasks below them
public function index(Client $client)
{
$tasks = $client->tasks()->get();
//dd($tasks);
return view('task.index', compact('tasks'));
}
or with projects
{
$projects = $client->projects()->with('tasks')->get();
return view('task.index', compact('projects'));
}
In this second example, you get a collection of projects with the tasks inside, so you can then show a list of projects and a list of tasks for that project

Reset a table data with an observable as its source

I have an observable that fills a table like this:
<table class="table table-borderless" style="width:44%;" *ngIf="(borrowers_main_data$ | async) as borrowers_main_data">
<tbody>
<tr>
<td width="8%">CDI:</td>
<td>
<strong>{{ borrowers_main_data.Cdi }}</strong>
And this is the code that fills the table:
public borrowers_main_data$ = this.service.cdiVariable$.pipe(
switchMap(cdiVariable => {return this.dataSource.getCustomer(cdiVariable).pipe(
catchError(error => {
if (error.error instanceof ErrorEvent) {
this.errorMsg = `Error: ${error.error.message}`;
} else {
this.errorMsg = `Error: ${error.message}`;
}
return of({} as Customer);
}))
}));
The problem is that in the case of a second search (after a successful one) that returns the Observable of the empty object the table stays populated with the previous data.

How to handle useState asynchronous in React hooks (in my case)

Here products state is null when I try to display the product. I know to handle this we can use useEffect again for displaying the product but still product state is null. Here is the part of the code that I tried to attempt.
function Product() {
const [products, setProducts] = useState(null);
useEffect(() => {
axios
.get("http://localhost:4000/products")
.then((res) => setProducts(res.data));
}, []);
useEffect(() => {
console.log(products); // Here still products is null
products.map((product) => (
<tr key={product.id}>
<td>{product.productName}</td>
<td>{product.productDesc}</td>
<td>{product.manufacturer}</td>
<td>{product.price}</td>
<td>{product.quantity}</td>
</tr>
));
}, [products]);
return <></>;
}
If I remove products.map then it is showing as two values first one is null and the second is an array of the object (i.e my data).
Right now, nothing will ever be rendered as the return is empty (almost).
Try
function Product() {
const [products, setProducts] = useState(null);
useEffect(() => {
axios
.get("http://localhost:4000/products")
.then((res) => setProducts(res.data));
}, []);
if (!products) {
return null;
}
return products.map(product => (
<tr key={product.id}>
<td>{product.productName}</td>
<td>{product.productDesc}</td>
<td>{product.manufacturer}</td>
<td>{product.price}</td>
<td>{product.quantity}</td>
</tr>
));
}
This is a typical example of lifting the state up to the higher-order component in React.js.
All states and API calls need to be written in your top-level-component.
import ProductItem from "./ProductItem";
function Product(){
const [products, setProducts] = useState(null);
useEffect(() => {
axios
.get("http://localhost:4000/products")
.then((res) => setProducts(res.data));
}, []);
return(
<table>
<thead>
<th>Name</th>
<th>Description</th>
<th>Manufacturer</th>
<th>Price</th>
<th>Qunatity</th>
</thead>
<tbody>
<ProductItem products={products} />
</thead>
</table>
);
}
Here, the products state is passed as a prop to ProductItem. Now the ProductItem component will have the list of the product's item which can be accessed as a prop.
function ProductItem({products}) {
useEffect(() => {
console.log(products); // getting the list of the product in the developer console,
}, [products]);
return (
<>
{products.map((product) => (
<tr key={product.id}>
<td>{product.productName}</td>
<td>{product.productDesc}</td>
<td>{product.manufacturer}</td>
<td>{product.price}</td>
<td>{product.quantity}</td>
</tr>
))}
</>;
);
}
export default ProductItem;

How to count rows in another table which contains foreign key and loop it foreach collection instance?

I have two tables which are connected each other.
their structures look like this.
modul_table
id | user_id | title | slug | platform
lecture_table
id | user_id | modul_id | title | content
I want to count how many rows in lecture_table where its modul_id = $id.
So this $id are the ids of my collection which retrieved from controller.
here's my controller:
public function index()
{
$modul = Modul::get();
$arr_lecture = [];
foreach ($modul as $key) {
$lecture = Lecture::where('modul_id', $key->id)->count();
array_push($arr_lecture, $lecture);
}
return view('func.lihatModul', compact('modul', 'arr_lecture'));
}
and in my view :
#php $i = 0 #endphp
#foreach($modul as $key)
<tr>
<td>{{$key->id}}</td>
<td>{{$key->title}}</td>
<td>{{substr($key->desc, 0, 75)}}</td>
<td>{{ $arr_lecture[$i++] }}</td>
#endforeach
and the result:
all my codes are working well, but is there any way just by using query builder or a function to do the same approach?
If you have defined the lectures relationship in your Modul model like so:
# Modul.php
public function lectures()
{
return $this->hasMany(Lecture::class);
}
Then, you could simple do this in your ModulController:
public function index()
{
$moduls = Modul::withCount('lectures')->get();
// ^^^^^^^^^^^^^^^^^^^^
return view('func.lihatModul')->withModuls($moduls);
} ^^^^^^^^^^^^^^^^^^^^^
This will add the lectures_count attribute to each $modul, so you can access it in your Blade view like this:
#foreach($moduls as $modul)
<tr>
<td>{{ $modul->id }}</td>
<td>{{ $modul->title }}</td>
<td>{{ substr($modul->desc, 0, 75) }}</td>
<td>{{ $modul->lectures_count }}</td> // <-----
#endforeach
Check the docs regarding this section: Counting related models.
If you have the one-to-many relationships set up properly as it explains in the docs https://laravel.com/docs/master/eloquent-relationships#one-to-many
So in your Modul.php model
public function lectures()
{
return $this->hasMany('App\Lecture');
}
and in your Lecture.php model
public function modul()
{
return $this->belongsTo('App\Modul');
}
then you should just be able to do
$modul = Modul::with('lectures')->get();
Then in blade
#foreach($modul as $key)
<tr>
<td>{{$key->id}}</td>
<td>{{$key->title}}</td>
<td>{{substr($key->desc, 0, 75)}}</td>
<td>{{ $key->lectures->count() }}</td>
#endforeach
If u want to leave your variant u don't need to use array_push better store value in array with $key
public function index()
{
$modul = Modul::get();
$arr_lecture = [];
foreach ($modul as $key) {
$lecture = Lecture::where('modul_id', $key->id)->count();
$arr_lecture[$key->id] = $lecture;
}
return view('func.lihatModul', compact('modul', 'arr_lecture'));
}
now $arr_lecture will have correct keys. Next in view
#foreach($modul as $key)
<tr>
<td>{{$key->id}}</td>
<td>{{$key->title}}</td>
<td>{{substr($key->desc, 0, 75)}}</td>
<td>{{ count($arr_lecture[key->id]) }}</td>
#endforeach
but Kennys version is really good

Show function at controller not getting value from index

I really get here to bother you only when I can't find an answer.
I don't know Why I get a null at show function at productoservicioevento. It's the same code that I use at grupo and there I get the id...
index at module productoservicioevento
#foreach($productoservicioeventos as $productoservicioevento)
<tr>
<td> {{ $productoservicioevento->idProductoServicioEvento }}></td>
<!--<td> {{ $productoservicioevento->strConcepto }}></td>-->
<td>{{ $productoservicioevento->dcmPrecio }}</td>
<td>{{ $productoservicioevento->evento->strNombreEvento }}</td>
</tr>
#endforeach
show function at productoservicioeventocontroller
public function show(ProductoServicioEvento $productoServicioEvento)
{
//
//$productoServicioEvento = ProductoServicioEvento::all();
dd($productoServicioEvento);
dd($productoServicioEvento->idProductoServicioEvento);
$productoServicioEvento = ProductoServicioEvento::find($productoServicioEvento->idProductoServicioEvento);
I get null when click at index
The module from productoservicioevento was actually copied from
index at grupo
#foreach($productoservicioeventos as $productoservicioevento)
<tr>
<td> {{ $productoservicioevento->idProductoServicioEvento }}></td>
<!--<td> {{ $productoservicioevento->strConcepto }}></td>-->
<td>{{ $productoservicioevento->dcmPrecio }}</td>
<td>{{ $productoservicioevento->evento->strNombreEvento }}</td>
</tr>
#endforeach
Everything is Ok at gruposcontroller, show function
public function show(grupo $grupo)
{
//
dd($grupo);
$grupo = grupo::find($grupo->idGrupo);
Everything goes fine there...
Te routes, Totally basic.
Route::resource('lockers','LockersController');
Route::resource('escuelas','EscuelasController');
Route::resource('grupos','GruposController');
Route::resource('productoservicioeventos','ProductoServicioEventosController');
Route::resource('horarioperiodicos','HorarioPeriodicosController');
Route::resource('eventos','EventosController');
I changed this.
public function show(ProductoServicioEvento $productoServicioEvento)
{
//
//$productoServicioEvento = ProductoServicioEvento::all();
dd($productoServicioEvento);
dd($productoServicioEvento->idProductoServicioEvento);
$productoServicioEvento = ProductoServicioEvento::find($productoServicioEvento->idProductoServicioEvento);
For this
public function show( $producto)
{
//
//dd($producto);
/*dd($productoServicioEvento->idProductoServicioEvento);*/
$productoServicioEvento = null;
$productoServicioEvento = ProductoServicioEvento::find($producto);
Now I'm able to work but don't know the reason why I had to change model to id...
So I'm totally stuck, please help.
Thanks in advance.

Resources