The problem here is that your template is not present at runtime. Angular 
Compiler takes metadata and your typescript code, and creates their 
internal representation of all the stuff. Basically, decorations are moved 
to something like CompiledComponent.annotations = { template: '...', ...  
}. But messing with that is a bit tricky + you have a problem of Angular 
potentially changing this internal stuff.

But if you still wanted it, you could write a custom component decorator 
that would do this magic.

If you wanted less magic, as an alternative, you can simply make your 
component *designed* this way, meaning, in the way that it expects optional 
different templates. Something that would work like this:

1. Import your login component.
2. Use it:

<login-component custom=true>
    <ng-template my-login-template> <!-- this is basically the template 
that you're overriding with.
        <select name="username">
           <option>Me</option>
           <option>The other guy</option>
        </select>
    </ng-template>
</login-component>

Then your component would have to know about this:

<div *ngIf="!custom">
    <input name="username">
</div>
<ng-content select="[my-login-template]"></ng-content>

Then depending on the "custom" prop (name it better, please), you would 
hook your listeners into different input fields. A bit tricky part is 
knowing if the custom template actually provides the proper things - e.g. 
if it finds or not a form element with [name="username] attribute in the 
example above.

What you can do for that part is simply fail - have the component throw if 
it doesn't find username and password fields. I can't think of a way to 
fail at dev time (e.g. have Code warn the user this field is missing) , but 
at least it would break some tests and the user(dev I mean) sees what the 
problem is in the console. When they come to your github screaming "no 
work!", you point them to the clear error message.

This looks a cleaner approach then tapping into Angular internals here..

Zlatko


On Friday, August 31, 2018 at 7:00:51 AM UTC+2, Codewise IO wrote:
>
>  
> I have created an authentication library @mylib/auth  to use across 
> various applications. It works great in that I just need to import it in my 
> app module, and I get all sorts of great components (LoginComponent, 
> RegisterComponent, ResetPasswordComponent, etc) and my AuthService provided 
> for me. Even more still, by importing AuthModule.routing() in my AppModule 
> definition I get all these routes defined for my app as well. '/sign-in', 
> '/register', '/reset-password'. So by adding just a couple of lines (below) 
> into any of my applications I get users and authentication. It's great and 
> I love it.
>
> @NgModule({
>  ...
>   imports: [
>      ...
>     AuthModule,
>     AuthModule.routing(),
>     ...
>
>  Now the catch is, that if I want to change the template for one of these 
> pages, I have to subclass the component. While that is simple enough, it 
> means I lose the magic of just importing AuthenticationModule.routing() in 
> my main module, so then I have to create a routing module and define all my 
> routes there...
>
> import { LoginComponent } from '@mylib/auth'
>
> @Component({
>   selector: 'app-login',
>   templateUrl: './login.component.html',
>   styleUrls: ['./login.component.css'],
> })
> export class DerivedLoginComponent extends LoginComponent {
>
> }
>
> So, while it's not the end of the world - I REALLY like just having those 
> 2 lines to add into my app to get my authentication components and urls. If 
> I could make it just 3 lines in order to change my template I would LOVE 
> it. Something like this:
>
> template.auth.login = '/templates/auth/login.component.html'
>
> @NgModule({
>  ...
>   imports: [
>      ...
>     AuthModule,
>     AuthModule.routing(),
>     ...
>
>
>
> So my  thoughts here was to create a variables called templates in a 
> single file mylib/auth/templates.ts, and pull in that variable in each of 
> my *.component.ts files and use it determine the which template to use.
>
> I was stopped very quickly as even just moving the @component definition 
> variable outside (like the code below) of the decorator causes errors in 
> the browser after compiling - just a blank page and in the console "cannot 
> find ./login.template.html"
>
> let ngComponent = {
>   selector: 'app-login',
>   templateUrl:  './login.component.html',
>   styleUrls: ['./login.component.css'],
> }
>
> @Component(
>   ngComponent
> )
> export class LoginComponent extends FormComponent  {
>
>
> I have plans to make a few more libraries in addition to the auth library  
> and the consuming apps will pretty much only want to change the template.
>
> Is there a solution to this problem (that works with AOT)? Maybe this 
> whole ordeal is a bit esoteric but I am loving the clean project folder and 
> just adding a few simple lines to get add powerful features. I'm willing to 
> jump through some hoops in the Auth library to make the consuming apps 
> super simple.
>
> Thanks in advance for any insight.
>
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Angular and AngularJS discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to angular+unsubscr...@googlegroups.com.
To post to this group, send email to angular@googlegroups.com.
Visit this group at https://groups.google.com/group/angular.
For more options, visit https://groups.google.com/d/optout.

Reply via email to