ngxs: Store not initialized when injected - ngxs

I am using ngxs 3.7.5 with Angular 14
// single slice
#State<EnvironmentStateModel>({
name: 'environment',
defaults: {
productionBuild: environment.production,
internalPlatform: detectInternalPlatform(window.location.hostname, window.location.port),
platform: detectPlattform(),
appVersion: environment.appVersion
}
})
#Injectable()
export class EnvironmentState {
}
I am injecting the store into a HttpInterceptor
export class MessageHeaderInterceptor implements HttpInterceptor {
constructor(private userService: UserService, private store: Store) {
console.log('constructor', this.store.selectSnapshot((appState: AppState) => appState));
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
console.log('intercept', this.store.selectSnapshot((appState: AppState) => appState));
//...
}
}
The console statement in the constructor shows {}, also the console statement in the first call to intercept. However consecutive calls to intercept show { environment: ... } that is with the environment slice properly initialized. I expect the store to be properly initialized when using it the first time. What am I doing wrong?

When you include the NgxsModule in the import, the EnvironmentState should be passed to the NgxsModule's .forRoot() function (if it's a root store), or .forFeature() function (if it's a lazy-loaded store).
You can find more details here:
https://www.ngxs.io/getting-started/installation
https://www.ngxs.io/advanced/lazy

Related

How to use PersistentUnorderedMap on NEAR contract using AssemblyScript? PersistentUnorderedMap does not appear in Contract Storage after init

In my contract I am attempting to use PersistentMap and PersistentUnorderedMap.
In my class I'm doing the following:
import { PersistentMap, PersistentUnorderedMap } from "near-sdk-core";
public vehicleOwners: PersistentMap<AccountId, VehicleOwner>;
public vehicleOwnersPmap: PersistentUnorderedMap<AccountId, VehicleOwner>;
constructor(public vehicle:string = 'Mini') {
this.vehicleOwners = new PersistentMap<AccountId, VehicleOwner>("vo"),
this.vehicleOwnersPmap = new PersistentUnorderedMap<AccountId,VehicleOwner>("pma")
}
// Model
#nearBindgen
class VehicleOwner {
constructor(public vehicleOwner: AccountId, public dateAcquired: string) {}
}
After running the init method near call $CONTRACT init --accountId $CONTRACT
If I check the contract's storage I see vehicleOwners but I do not see vehicleOwnersPmap.
state: {
"vehicle": "Mini",
"vehicleOwners": {
"_elementPrefix": "vo::"
}
}
I figured out that after running one transaction and then seeing storage I can now see in state the PersistentUnorderedMap instance variable being set to null. I am still not sure why it won't show after init. This is different from PersistentMap where you can see it on state after init.
state: {
"vehicle": "Mini",
"vehicleOwnersPmap": null,
"vehicleOwners": {
"_elementPrefix": "vo::"
}
}

Nativescript Audio: Access Player across pages?

I am using the nativescript-audio plugin for my iOS angular NS app.
I want to start playing an audio file on one page, navigate to a different page, and manipulate the audio player from that second page. So I need to access the player instance on a page that is different than where the instance was created.
For example, start playing audio on Page 1, and then pause the player on Page 2.
How can I do this?
I have tried saving the player instance in local storage to access later, but local storage saves items as strings, so I need to convert the player instance to a string, which doesn't work.
As #Brad Martin recommended, it works to put the player in an injectable Angular service and access it app wide. So, for example:
Create the Service:
app.module.ts:
import { AudioService } from "./audio-service"
#NgModule({
...
providers: [
AudioService //registers the service with the provider's metadata
]
})
audio-service.ts:
import { Injectable, EventEmitter } from '#angular/core'
import { TNSPlayer } from "nativescript-audio"
#Injectable()
export class AudioService {
private _player: TNSPlayer;
playEvent = new EventEmitter<any>()
constructor() {}
playAudio(audioFilePath){
this._player = new TNSPlayer();
this._player.initFromFile({
audioFile: audioFilePath,
loop: false,
}).then(()=>{
this._player.play()
this.playEvent.emit('File is playing now')
})
}
pausePlayer(){
this._player.pause()
}
}
Access the Service:
cool-component.ts:
import {OnInit} from #angular/core"
import { AudioService } from "~/audio-service"
import { Page } from "tns-core-modules/ui/page"
#Component({...})
export class CoolComponent implements OnInit {
public getPlay: any;
constructor(private _audioService: AudioService) {}
ngOnInit(): void {
this.getPlay = this._audioService.playEvent.subscribe((value)=>{
console.log(value) //when audio is playing, should say 'File is playing now'
}
this.page.on('navigatingFrom', (data) => {
if (this.getPlay){
this.getPlay.unsubscribe() //unsubscribe from service emitter when exit the page--to avoid multiplying the subscription every time you go to this page
})
}
playAudioFromService(audioFilePathDetail){
this._audioService.playAudio(audioFilePathDetail)
}
pauseAudioFromService(){
this._audioService.pausePlayer()
}
}

Expected 2 arguments, but got 1.ts(2554) core.d.ts(8054, 47): An argument for 'opts' was not provided

This is a part of my code that I get this error:
Expected 2 arguments, but got 1.ts(2554)
core.d.ts(8054, 47): An argument for 'opts' was not provided.
from here:
import {ViewChild, ChangeDetectorRef, AfterViewInit} from "#angular/core";
import {RadSideDrawerComponent, SideDrawerType} from "nativescript-telerik-ui/sidedrawer/angular";
export class DrawerPage implements AfterViewInit {
#ViewChild(RadSideDrawerComponent) protected drawerComponent: RadSideDrawerComponent;
protected drawer: SideDrawerType;
constructor(private _changeDetectorRef: ChangeDetectorRef) { }
ngAfterViewInit() {
this.drawer = this.drawerComponent.sideDrawer;
this._changeDetectorRef.detectChanges();
}
protected openDrawer() {
this.drawer.showDrawer();
}
protected closeDrawer() {
this.drawer.closeDrawer();
}
}
I can't understand what is the problem? I am new learner who follows a tutorial video to learn NativeScript!
In Angular 8 , ViewChild takes 2 parameters:
Try like this:
#ViewChild('nameInput', { static: false }) nameInputRef: ElementRef;
Explanation:
{ static: false }
If you set static false, the component ALWAYS gets initialized after the view initialization in time for the ngAfterViewInit/ngAfterContentInit callback functions.
{ static: true}
If you set static true, the initialization will take place at the view initialization at ngOnInit
By default you can use { static: false }. If you are creating a dynamic view and want to use the template reference variable, then you should use { static: true}
For more info, you can read this here
Thank you.
You are using nativescript-telerik-ui/sidedrawer and that is not supported by latest version of Nativscript.This package has been deprecated.
For side drawer, use nativescript-ui-sidedrawer.

angular2firebase - multiple instances using Angular 6

I'm upgrading to Angular 6 using AngularFire2. My app referenced 2 Firebase projects using code like this to create the database reference:
public initFirebaseApp(config: FirebaseAppConfig, firebaseAppName: string) {
this._db = new AngularFireDatabase(_firebaseAppFactory(config, firebaseAppName));
}
This code is now broken. I get this:
ERROR in src/app/services/firebase.service.ts(24,25): error TS2554: Expected 5 arguments, but got 1.
Thanks!
AngularFire now support many more configuration objects via Injection now, which is why it's expecting more arguments. It currently takes:
constructor(
#Inject(FirebaseOptionsToken) options:FirebaseOptions,
#Optional() #Inject(FirebaseNameOrConfigToken) nameOrConfig:string|FirebaseAppConfig|undefined,
#Optional() #Inject(RealtimeDatabaseURL) databaseURL:string,
#Inject(PLATFORM_ID) platformId: Object,
zone: NgZone
)
Though now that we support dependency injection, I wouldn't suggest directly initializing like you are to support multiple apps. We have an open issue for documenting this but you can now inject different FirebaseOptions via the FirebaseOptionsToken into different components, if you need multiple databases in the same component use something like this:
#Injectable()
export class AngularFireDatabaseAlpha extends AngularFireDatabase { }
#Injectable()
export class AngularFireDatabaseBeta extends AngularFireDatabase { }
export function AngularFireDatabaseAlphaFactory(platformId: Object, zone: NgZone): Project1AngularFireAuth {
return new AngularFireDatabaseAlpha(environment.firebase[0], 'alpha', undefined, platformId, zone)
}
export function AngularFireDatabaseBetaFactory(platformId: Object, zone: NgZone): Project2AngularFireAuth {
return new AngularFireDatabaseBeta(environment.firebase[1], 'beta', undefined, platformId, zone)
}
#NgModule({
...,
providers: [
...,
{ provide: AngularFireDatabaseAlpha, deps: [PLATFORM_ID, NgZone], useFactory: AngularFireDatabaseAlphaFactory },
{ provide: AngularFireDatabaseBeta, deps: [PLATFORM_ID, NgZone], useFactory: AngularFireDatabaseBetaFactory },
...
],
...
})
Then you can just rely on Dependency Injection to get AngularFireDatabaseAlpha and AngularFireDatabaseBeta into your component.

.NET Core + Angular-CLI App - can't pass data from api to components [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I'm building an ASP .NET Core App with Angular-CLI using this tutorial.
App works great, I got pre-build event to ng build before starting the app in VS, it works OK. I also can successfully get to my API over localhost:port/api/[controller] (in this case it would be Contacts as it's supposed to be a contact book).
Now, I'm trying to have Angular get the data directly from API. For this reason, I created a IContact interface, a ContactService and I pass it onto ContactComponent which is supposed to display it.
I might be making a silly mistake here (my skills are very basic), but for some reason I don't even see the object .json coming in through the network logs when I run the app (before trying to pass it to the view I'm trying to ensure I'm getting the data from the API first).
I might be doing something wrong (so I encourage you to reply even if you think you might be saying silly-obvious stuff) but here's my questions:
Should my code below work (not attaching imports though, I think I got all of them but check me ;-))? I'm not talking super-efficient or stuff, just basic to get the job done.
What is the best way to see if service to getAPI is working? Would that be network logging in your browser if you just import the service into the component and try to call the get method? Or is there another way?
Is my logic and approach towards the general architecture of the app OK or am I getting something wrong? :-)
contact.service.ts
const API_URL = environment.apiUrl;
#Injectable()
export class ContactService {
constructor(private http: Http) { }
public getContacts(): Observable<IContact[]> {
return this.http.get(API_URL)
.map((response: Response) => <IContact[]>response.json())
.catch(this.handleError);
}
private handleError(error: Response) {
console.error(error);
return Observable.throw(error.json().error || 'Server error')
}
}
icontact.ts
export interface IContact {
id: number;
firstName: string,
lastName: string,
address: string,
telephone: string
}
contact.component.ts
#Component({
selector: 'app-contact',
templateUrl: './contact.component.html',
styleUrls: ['./contact.component.css'],
providers: [ContactService]
})
export class ContactComponent implements OnInit {
private _contactService: ContactService;
private contactlist: IContact[];
constructor() {
}
public ngOnInit() {
this._contactService.getContacts()
.subscribe((contacts) => { this.contactlist = contacts });
}
}
Any other code requirements or anything - let me know. All feedback is appreciated. Thanks!
I have slightly changed your code.
File icontact.ts. I have made IContact a simple type. You can make it an interface back to support your object shape.
export type IContact = string;
File contact.service.ts. We call the /api/values API that is created by default in a new ASP.NET Core Web API project if you follow the tutorial you mentioned.
import { Injectable } from "#angular/core";
import { Http } from "#angular/http";
import { Observable } from "rxjs/Observable";
import 'rxjs/add/operator/map'
import { IContact } from "./icontact";
const API_URL = '/api/values'; // environment.apiUrl;
#Injectable()
export class ContactService {
constructor(private http: Http) { }
public getContacts(): Observable<IContact[]> {
return this.http.get(API_URL)
.map(response => <IContact[]>response.json());
}
}
File contact.component.ts. The template simply displays the list.
import { Component, OnInit } from "#angular/core";
import { ContactService } from "./contact.service";
import { IContact } from "./icontact";
#Component({
selector: 'app-contact',
template: '<div *ngFor="let contact of contactList">{{contact}}</div>',
providers: [ContactService]
})
export class ContactComponent implements OnInit {
private contactList: IContact[];
constructor(private contactService: ContactService) { }
public ngOnInit() {
this.contactService.getContacts().subscribe(
(contacts) => { this.contactList = contacts; },
(error) => { console.log(error); }
);
}
}
File app.component.html. Display your component on the application's page.
<app-contact>Wait...</app-contact>
File app.module.ts. Import HttpModule. That fixes one of the error messages on your screenshot.
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { HttpModule } from '#angular/http';
import { AppComponent } from './app.component';
import { ContactComponent } from "./contact.component";
#NgModule({
declarations: [AppComponent, ContactComponent],
imports: [BrowserModule, HttpModule],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
In the Configure method in Startup.cs, make sure you put the app.Use(...) call before app.UseStaticFiles().
Since you serve your Angular app from wwwroot by a ASP.NET Core middleware, the host is the same for the Angular app and the Web API, so you don't need to configure CORS for that setup.
By the way, you may be interested in taking a look at the Angular CLI Templates on Visual Studio Marketplace. (Disclaimer: I'm the author.) The Item Template supports your project setup out-of-the-box.

Resources