Send arrays to different component via BehaviorSubject Angular - arrays

im developing an admin panel where the admin can see all the bookings that have been requested and select those who he will accept; and I want to display those 'accepted' bookings in a different tab (different component, in a different route). Im using a SharedService with a BehaviorSubject but it doesnt work: All I get in the 2nd component is an anonymousSubject array, which is empty. Im not showing the first component which sends the booking to the service cause thats working fine.
Help please!
shared Service
import {Injectable} from '#angular/core';
import {BehaviorSubject} from 'rxjs';
import {Turno} from '../models/turno';
#Injectable({
providedIn: 'root',
})
export class SharedService{
private acceptedBookings=[];
public acceptedBookingsSubject= new BehaviorSubject<Turno[]>([]);
//public turno:Turno;
constructor(){
}
addToAccepted(turno : Turno){
this.acceptedBookings.push(turno);
this.acceptedBookingsSubject.next(this.acceptedBookings);
console.log(this.acceptedBookingsSubject);
}
}
and here is the second component.
Second component, which consumes the service and has to display the array.
import { Component, OnInit} from '#angular/core';
import {SharedService} from '../../services/shared.service';
import {Observable} from 'rxjs';
import {Turno} from '../../models/turno';
import {share} from 'rxjs/operators';
#Component({
selector: 'app-turnoaceptado',
templateUrl: './turnoaceptado.component.html',
styleUrls: ['./turnoaceptado.component.css'],
providers:[SharedService]
})
export class TurnoaceptadoComponent implements OnInit {
public acceptedBookings:Observable<Turno[]>;
ngOnInit(): void {
}
constructor(private _sharedService: SharedService) {
this._sharedService.acceptedBookingsSubject.pipe(share());
}
}
And in the html of the 2nd component im using the async pipe |

At ngOnInit, just add:
this.acceptedBookings = this._sharedService.acceptedBookingsSubject.asObservable();
Then you can choose if you prefer to create a subscription on it or use pipe async.
Additional tip, once you set the SharedService with { providedIn: 'root' }, you don't need to put the SharedService on any providers array.
I have created a demo: stackblitz

Related

How to integrate Django Rest Framework Api with a front in AngularJS?

This is my first contact with AngularJS. I would like to integrate the api with a front in Angular, my goal is just to return a list of data, making it as simple as possible is my goal.
[link][1] Setup for server communication
Before you can use HttpClient, you need to import the Angular HttpClientModule. Most apps do so in the root AppModule.
app/app.module.ts (excerpt)
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { HttpClientModule } from '#angular/common/http';
You can then inject the HttpClient service as a dependency of an application class, as shown in the following ConfigService example.
app/config/config.service.ts (excerpt)
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable()
export class ConfigService {
constructor(private http: HttpClient) { }
}
The HttpClient service makes use of observables for all transactions. You must import the RxJS observable and operator symbols that appear in the example snippets. These ConfigService imports are typical.
app/config/config.service.ts (RxJS imports)
content_copy
import { Observable, throwError } from 'rxjs';
import { catchError, retry } from 'rxjs/operators';

Angular downgradeComponent not being created

I have just setup a hybrid AngularJS / Angular 5 application with downgradeModule. I have converted a very small component from AngularJS to Angular but it is never being created. I have put console.logs throughout the component to see if certain bits are called and others not. The file is loaded but the component never is.
I have read what feels like hundreds of tutorials but I must be missing something.
Note that I got this far in converting the component, realised it was not being created, then stopped porting the rest. Hence why driverImage is not currently on the converted component.
Here is a stackblitz with a test component that shows it not working https://angularjs-q1vrpe.stackblitz.io/
Bootstrap
import * as angular from "angular";
import { downgradeModule } from "#angular/upgrade/static";
import { platformBrowserDynamic } from "#angular/platform-browser-dynamic";
import { StaticProvider } from "#angular/core";
import { MainAngularModule } from "./app.module";
import "./index.module";
const bootstrapFn = (extraProviders: StaticProvider[]) => {
console.log("1"); <--- never output!
const platformRef = platformBrowserDynamic(extraProviders);
return platformRef.bootstrapModule(MainAngularModule);
};
const downgradedModule = downgradeModule(bootstrapFn);
angular.module('angularJsModule', ['myApp', downgradedModule]);
angular.bootstrap(document, ['angularJsModule']);
App.Module (MainAngularModule)
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { UpgradeModule } from '#angular/upgrade/static';
#NgModule({
imports: [
BrowserModule,
UpgradeModule
],
declarations: [Ng2TestComponent, DriverImageComponent],
entryComponents: [Ng2TestComponent, DriverImageComponent]
})
export class MainAngularModule {
// Empty placeholder method to satisfy the `Compiler`.
ngDoBootstrap() { }
}
index.module (Stripped most of the dependencies out for brevity)
angular
.module("myApp", [
"constants",
"ngMaterial",
"ngSanitize", ... ]);
The newly converted Component:
import { Component, Input, OnInit, OnChanges } from '#angular/core';
import { IDriver } from "../interfaces/IDriver";
console.log("here"); // --> This is hit
#Component({
selector: "driver-image",
template: `<div class="driver-image" ng-style="{'background-image' : 'url('+$ctrl.driverImage+')'}"></div>`
})
export class DriverImageComponent implements OnInit, OnChanges {
#Input() driver: IDriver;
#Input() small: boolean;
constructor() {
console.log("1"); // --- Not hit
}
ngOnInit() {
console.log("ONINITNINTT"); // --> Not hit
}
ngOnChanges() { }
}
The related modules.ts
import { downgradeComponent } from "#angular/upgrade/static";
...
.component("driverImage", downgradeComponent({ component: DriverImageComponent }))
The answer is actually really simple, it just took me forever to see it.
Contrary to what you might believe, you need to change your AngularJS component to be registered as a directive, NOT, a component.
without a Stackblitz this is pretty hard to reproduce (btw do you have any errors in the console?). I just write down some suggestions that you can try. If you tell me what worked, I'll update my answer
instead of import { platformBrowser } from "#angular/platform-browser"; use this one instead import { platformBrowserDynamic } from '#angular/platform-browser-dynamic'; (can't quite tell you the difference but platform-browser does not work in my projects)
Ok while writing this I think I found the answer. Your problem is you are not loading the component that should be downgraded in your Angular 5 application - everything you want to downgrade still needs to be properly loaded in Angular 5 itself. So try adding a entryComponents: [DriverImageComponent] to your App.Module
Edit:
Ok based on your comment it looks like your Application is not even bootstrapped. Are you sure you are using your component on the page that you are currently using? If the component is not being used, it will not be loaded and Angular won't be bootstrapped.
There are certain scenarios where you need to force this bootstrapping in the beginning.
Create an Bootstrap component
import { Component } from '#angular/core';
#Component({
selector: 'my-bootstrap',
template: '',
})
export class BootstrapComponent {}
Add it to your App.Module
declarations: [
BootstrapComponent,
],
entryComponents: [
BootstrapComponent,
],
Force it to be loaded in your main index.html by adding <my-bootstrap></my-bootstrap in the beginning of the <body>

How to add head tag with in components for multi page website

I need to add some data in head tag like changing the title , description etc for each page
Use Title service to assign dynamic titles to all pages. For eg:
In app.module.ts import Title and add to provider
import { BrowserModule, Title } from '#angular/platform-browser';
...
providers: [Title],
Import Title service in your page components and assign title string to them
import {Title} from '#angular/platform-browser';
...
export class HomeComponent implements OnInit {
constructor(private titleService: Title) { }
ngOnInit() {
this.titleService.setTitle('Home');
}
}

Can't resolve parameters for a component from inside an injectable

I'm trying to import a component into my injectable service, but it seems that I'm doing something wrong. This happens for other pages in similar situations as well. The current situation seems to happen because the LoginPage that I'm trying to import into SessionService requires SessionService, which smells of an infinite loop somewhere. Any ideas on how I should resolve it other than not including the page component in the injectable SessionService?
My current architecture is built so that I need to redirect to login page if session does not exist. Ionic NavController requires a page component for pushing onto navigation stack. Alternate ways of solving the redirection problem are welcome, but I would also like to understand why this is happening.
Uncaught Error: Can't resolve all parameters for LoginPage: (?, ContentService).
session.service.ts
#Injectable()
export class SessionService {
constructor(private content: ContentService) {}
}
login.page.ts
#Component({
templateUrl: './login.page.html'
})
export class LoginPage {
constructor(public session: SessionService,
public content: ContentService) {
}
and for those who requested it, content.service.ts
#Injectable()
export class ContentService {
constructor(private authHttp: AuthHttp) {
}
}
app.module.ts
#NgModule({
declarations: [
LoginPage
],
entryComponents: [
LoginPage
],
providers: [
SessionService,
ContentService
]
})
export class AppModule {
}
I'm using Angular 2.2.1 with Ionic 2.0.0-rc.4.
content.service.ts
#Injectable()
export class ContentService {...}
Add this also like SessionService

angular2 inject Router in component constructor error if no elvis operator

When my app starts, I want the route /home to be displayed by default.
The "useAsDefault: true" property to the route definition is not implemented yet on the Angular 2 version I use.
To solve the problem I thought doing this in app.component.ts (which is what you find in many examples on the net):
export class AppComponent implements OnInit {
constructor(private _router: Router) {}
ngOnInit() {
this._router.navigate(['/home']);
}
}
But I get:
"Error:(29, 12) TS2346: Supplied parameters do not match any signature of call target."
If I add the Elvis operator, it works, I don't get any error:
export class AppComponent implements OnInit {
constructor(private _router?: Router) {}
ngOnInit() {
this._router.navigate(['/home']);
}
}
Could someone help me understand why?
My app.component.ts file:
import {Component, OnInit} from '#angular/core';
import {Router, Routes, ROUTER_DIRECTIVES } from '#angular/router';
import {NavbarComponent} from "./navbar.component";
import {UsersComponent} from "./users.components";
import {PostsComponent} from "./posts.component";
import {HomeComponent} from "./home.component";
#Component({
selector: 'my-app',
templateUrl: 'app/app.component.html',
directives: [NavbarComponent, ROUTER_DIRECTIVES]
})
#Routes([
{path: '/home', component: HomeComponent},
{path: '/users', component: UsersComponent},
{path: '/posts', component: PostsComponent}
])
export class AppComponent implements OnInit {
constructor(private _router?: Router) {}
ngOnInit() {
this._router.navigate(['/home']);
}
}
If I add the Elvis operator, it works, I don't get any error
Minor: This is not called the elvis operator. Its just syntax to denote optional parameters (reference https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#3922-parameter-list)
Could someone help me understand why
the error Supplied parameters do not match any signature of call target points you to the fact that something is calling the constructor without providing all the parameters. That code is not shown in your question but you now know why (when you mark the parameter as optional you silence that error for obvious reasons)

Resources