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
Related
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.
I don't see an example on how to use accomplish what Host does (inject parent reference into child) in ES6.
#Component({ ... })
class PlayButton {
constructor(#Host() playerService: PlayerService) {
}
}
Any idea on how we could achieve this?
There is a Host variable, which may be used with any Directives.Not sure if there is #Host decorator.
Also if you have to inject some service you may use providers in the component decorator.
you may look into Angular API for reference.
For Host implementation you may look into Attribute Directives implementation.
Update
you may try ContentChildren decorator.
#Directive({
selector: 'someDir'
})
class SomeDir {
#ContentChildren(ChildDirective) contentChildren: QueryList<ChildDirective>;
ngAfterContentInit() {
// contentChildren is set
}
}
For reference you may check Angular API
I have a NavBar Component which loads the QApi Service, the QApi Service loads the UserService, but I get the following error:
EXCEPTION: No provider for UserService! (NavBarComponent -> QApi -> UserService)
Either I simply don't get the concept of dependency injection, I made a stupid error, or this is just way to complicated compared to native development... Thanks for your help.
Here my code:
UserService:
import {Injectable} from 'angular2/core';
//import {User} from '../data-source-mocks/users';
#Injectable()
export class UserService {
public isAuthenticated = true;
}
QApi Service:
import {Injectable} from 'angular2/core';
import {UserService} from '../user/user.service';
#Injectable()
export class QApi {
constructor(private _userService: UserService) {}
}
NavBar Component:
import {Component} from 'angular2/core';
import {QApi} from '../../services/q-api/q-api';
#Component({
selector: 'nav-bar',
template: `Test NavBar`,
providers: [QApi]
})
export class NavBarComponent {
private _isAuthenticated = false;
constructor(private _QApi: QApi) {}
}
EDIT:
First of all: Thanks for alle the great answers each and every single one helped me to understand dependency injection better, especially this article: https://angular.io/docs/ts/latest/guide/hierarchical-dependency-injection.html
I changed my QApi class to this:
import {Injectable, Inject, Injector} from 'angular2/core';
import {UserService} from '../user/user.service';
import {CardService} from '../card/card.service';
#Injectable()
export class QApi {
constructor() {
var _injector = Injector.resolveAndCreate([UserService,
CardService]);
this.userService = _injector.get(UserService);
this.cardService = _injector.get(CardService);
}
}
Now it works like I hoped it would. Cant thank you guys enough!!
Add UserService to the component providers:
#Component({
selector: 'nav-bar',
template: `Test NavBar`,
providers: [QApi, UserService] // <- add UserService here
})
export class NavBarComponent { /* ... */ }
Here are two good articles to better understand Angular2 Dependency Injection:
blog.thoughtram.io: Dependency Injection in Angular2
blog.thoughtram.io: Injecting services in services in Angular 2
In fact both previous responses are true! ;-)
You need to define the services:
Application level. Within the second parameter of the bootstrap function. It contains the list of the providers that are available for the whole application.
bootstrap(App, [UserService, QApi, ...]);
Component level. Within the providers attribute of the Component annotation. In this case, this is only configured for this component and you need to define this for each component where the QApi service.
#Component({
selector: 'nav-bar',
template: `Test NavBar`,
providers: [QApi, UserService]
})
You also mix things. I mean you can put the UserService provider at the application level and QApi at the component level. In fact what is important is that Angular can find providers for all the involved elements in the processing chaining (with dependency injection). They can come from either component level (1st) or application level (2nd).
Hope that it gives you some additional hints following alexpods and MichaelOryl great answers ;-)
Thierry
List the services in your bootstrap call (wherever you are handling that). Something like the following should work:
bootstrap(App, [UserService, QApi, COMMON_DIRECTIVES, ROUTER_DIRECTIVES, ROUTER_PROVIDERS, HTTP_PROVIDERS]);
providers// directives added here are available to all children
Then you will have a single instance of each of those services available to the rest of your application.
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.
I have a custom component and try to test for the emitted events
My component looks like this:
#Component(
selector: "my-component",
templateUrl: 'component/my-component.html',
useShadowDom: false,
publishAs: "ctrl"
)
class MyComponent implements ScopeAware {
Scope scope;
String value = "foo"
void onButtonClick(){
scope.emit('on-select', value);
}
}
The component emits a 'on-select' event when a button is clicked. Works like expected but since i'm a huge fan of testing i want to test for that event.
Is this possible in angular 0.14.0?
I write my tests like the tests in angulardart-sample-app
The whole component testing has really a lot of boilerplate and is everything else then fun to write. Are there simpler ways for component testing in 0.14.0 or the future?