can I put a variable in ngx-extended-pdf-viewer and pass it in from URL - ngx-extended-pdf-viewer

I'm hoping there's no such thing as a dumb question in this forum.
I've seen the ngx-extended-pdf-viewer demo at https://www.pdfviewer.net/extended-pdf-viewer/multiple-documents which loads a new pdf when selected from a list on that demo page, but I'm wondering how I could pass the source variable to the pdf-viewer via the URL Like:
www.myviewer/index.html?source=pdfNAME
(index.html is the 'starter' version I built according to https://pspdfkit.com/blog/2021/how-to-build-an-angular-pdf-viewer-with-pdfjs/)
and then have that variable used to select the source location from an array. Such as:
var pdfSource = [
{
selector: 'app-root_Selector',
templateUrl: './app.component.html',
styleUrls: ['./app.component_A.css'],
name:'myNewPdf'},
}]
(( and where would I put that array?)

Are you familiar with Angular routing? Here's a very short run-down:
You need to define a route with a variable:
{ path: ':path', component: ExampleComponent },
Now your component can query the variable part of the URL:
export class ExampleComponent implements OnInit {
public pdfFile!: string;
constructor(private router: Router, private currentRoute: ActivatedRoute) { }
ngOnInit(): void {
this.currentRoute.paramMap.subscribe(route => {
this.pdfFile = route.get("path");
});
}
When you call your application with an URL like https://example.com/example.pdf, the URL snippet example.pdf is copied to the variable pdfFile, and you can use is for the [src] attribute:
<ngx-extended-pdf-viewer [src]="pdfFile">
I suppose that was a pretty fast description, but now you're better equipped to understand the official and lengthy documentation.
Side remark: The instructions on https://pspdfkit.com/blog/2021/how-to-build-an-angular-pdf-viewer-with-pdfjs/ are good, but setting up ngx-extended-pdf-viewer has become even simpler in the meantime (see the instructions on the showcase.

Related

NestJS - question regarding service-mocking

I'm currently rewriting our plain node API-server in NestJS and I've encountered the following issue: I have a CacheService which acts as a wrapper around redis and which is injected in various other services.
Now, if the client-request contains a custom-header (key: x-mock-redis, value: someRedisMockKey) and if the server runs in debug mode, instead of calling redis, a mocked json-value should be returned (the value is read from a file with the name someRedisMockKey).
I could set the scope of my CacheService to "Request" and inject the client-request, allowing me to check if the mocking-header exists and return the mocked value there if running in debug-mode.
But I find this counterintuitive as I'd have logic violating the single responsibility principle and which should not run in production-mode. Also I'd prefer my CacheService to have default scope instead of "Request".
Any recommendations how to do this more elegantly?
In advance, sorry if I misunderstood the question or constraints, will try to paraphrase them and point out how it should look like, I suppose.
production always uses Redis
you can set up the app instance on different port so that it is fully separated from 'staging' (or other) app instance
If you can fulfill the second condition, you can make use of custom modules and apply different client-wrapper (strategy) for your service:
Custom provider for Cache module
import * as redis from 'redis'
import { INTERNAL_CACHE_CLIENT, INTERNAL_CACHE_MODULE } from './cache.constants'
import { CacheModuleAsyncOptions, InternalCacheOptions } from './cache.module'
import CacheClientRedis from './client/cache-client-redis'
// ...
export const createAsyncClientOptions = (options: CacheModuleAsyncOptions) => ({
provide: INTERNAL_CACHE_MODULE,
useFactory: options.useFactory,
inject: options.inject,
})
export const createClient = () => ({
provide: INTERNAL_CACHE_CLIENT,
useFactory: (options: InternalCacheOptions) => {
const { production, debug, noCache, ...redisConfig } = options
// pardon for the ifs ; )
if (noCache) {
return new CacheClientInMemory()
}
if (production) {
return new CacheClientRedis(redis.createClient(redisConfig))
}
if (debug) {
return new MockedCache()
}
return new CacheClientMemory()
},
inject: [INTERNAL_CACHE_MODULE],
})
as noticed, you can have any wrapper around CacheClient, which, in your case, would serve data from file. For simplicity, the example of interface being implemented by any cache client could be:
export interface CacheClient {
set: (key: string, payload: string) => Promise<boolean>
get: (key: string) => Promise<string | null>
del: (key: string) => Promise<boolean>
}
Now on, as we have let the module decide which strategy should be used, service just needs:
constructor(
#Inject(INTERNAL_CACHE_CLIENT) private readonly cacheClient: CacheClient) {
}
Feel free to point out if it still breaks principles or you really need to decide it during runtime.
Cheers!

use service as decorator

Is there a way to do a static decorator on routes that check certain logics before loading?
example
have a auth decorator
#Injector()
class Auth{
Auth(){
if (isLoggedIn){
proceed();
}else{
showLoginRoute();
}
}
}
and use like
#Auth()
#Component(
selector: 'auth-view',
styleUrls: const ['login_component.css'],
template:
'<router-outlet name="dashboard" [routes]="routes.authView_routes"></router-outlet>',
directives: const [materialDirectives, routerDirectives, coreDirectives],
providers: const [r.Routes, materialProviders, Auth],
)
class Dashboard{
....
}
I know what i want to do but just not sure how to get it done. Currently i am importing services across several components and doing lots of repetition and i want to avoid that as much as possible.
Dart doesn't support anything like decorators in TS.
What might work for you is code generation like it's done in build_value, json_serializable, ...
https://github.com/dart-lang/build

How to fetch data before navigating in AngularDart?

I want to fetch all data from remote service at once before routing to Profile.
I find typescript version angular have Resolve to help to fetch data before navigating. But I cannot find any example in Dart version ( angular2: ^3.0.0).
#RouteConfig(const [
const Route(path: '/', name: 'Home', component: HomeComponent, useAsDefault: true]),
const Route(path: '/profile', name: 'Profile', component: ProfileComponent),])
class AppComponent implements OnInit{
}
Anyone know how to handle it by using Dart?
The current router in Angular.dart doesn't have Resolve.
Depending on what exactly you try to accomplish, there might be different workarounds.
Usually just wrapping the content of the components template with
<template [ngIf]="data != null"> ... </template>
should do, and then assign to data when it's available and the component will be shown.
Another more generic way might be to create a custom MyRouterOutlet that might extend RouterOutlet and customize it so that it delays adding the component until an event was received.
Add to the RouterOutlet
#HostBinding()
dataArrived() {
// call the code that actually adds the component
}
then use it like
<router-outlet fetchDataDirective></router-outlet>
and a directive like
#Directive(selector: '[fetchDataDirective]')
class FetchDataDirective implements OnInit {
final DataService dataService;
FetchDataDirective(this.dataService);
#Output()
get dataArrived => _dataArrived.stream;
final _dataArrived = new StreamController();
ngOnInit() async {
await dataService.fetchData();
}
}
that emits the event the RouterOutlet waits for.
It was also mentioned that a new router for Angular.dart is work in progress (might still take a while though).

Angular 2. How to set initial state from Asp.net MVC View

How can I set initial state of Angular 2 app from view?
I have a controller that must pass initial state throw the view to angular 2 component.
Currently you can't pass data to the root level component via a property, but you can however define a global variable outside the component and refer to it in your component. This might not be ideal, but perhaps not too bad either.
jquery is an example of this. In the below example the global jquery variable is referenced from my component. You could do the same with your own global variable. You could use server side rendering to dynamically create your global variable when the page renders.
import {Component, ElementRef, Inject, OnInit} from 'angular2/core';
declare var jQuery:any;
#Component({
selector: 'jquery-integration',
templateUrl: './components/jquery-integration/jquery-integration.html'
})
export class JqueryIntegration implements OnInit {
elementRef: ElementRef;
constructor(#Inject(ElementRef) elementRef: ElementRef) {
this.elementRef = elementRef;
}
ngOnInit() {
jQuery(this.elementRef.nativeElement).find('.moving-box').draggable({containment:'#draggable-parent'});
}
}
Why don't you hydrate the initial state of the application by calling a WebApi endpoint in ngOnInit()? That way your application is relying on a standard HTTP response rather than a piece of MVC infrastructure...

Angular2 Inject components into other components

I'm messing around with Angular2 and I'm wanting the ability to inject one component into another based on the bootstrapped bindings.
class HelloComponent {
name: string;
}
#Component({
selector: 'hello'
}
#View({
template: `<h3>Hello {{ name }}</h3>`
})
class HelloBobComponent extends HelloComponent {
constructor() {
this.name = 'Bob';
}
}
#Component({
selector: 'app'
}
#View({
directives: [HelloComponent]
template: `<h1>Welcome to my Angular2 app</h1>
<hello></hello>`
}
class AppComponent {
}
bootstrap(AppComponent, [
bind(HelloComponent).toClass(HelloBobComponent)
]);
Here I'm using HelloComponent as a token that I want Angular2's Injector to resolve HelloBobComponent. I'm doing this so that I can swap components in and out based on the current app configuration. The above example obviously doesn't work. Is this possible using one of the frameworks decorators? I haven't found an answer yet digging though blogs or the source.
edit: To clarify, how do I get the directives property on the View decorator to treat HelloComponent as a di token instead of a type.
This is currently not supported as of alpha37. The compiler resolves directives passed in the View decorator by either type or binding but does not look up from the parent injector.
For example:
#View({
url: '...',
directives: [
Directive1,
bind(Directive2).toClass(Directive2Impl),
]
})
The intention for the "directives" property here was only to prevent selector naming collision. Later bind support was added to aid in testing.
The only solution I can think of without editing the compiler function would be to maintain an external Injector and resolve types on component declaration.

Resources