bypassSecurityTrustHtml stripts angular form tags

1,923 views
Skip to first unread message

Turkel

unread,
Sep 30, 2017, 7:48:02 AM9/30/17
to Angular and AngularJS discussion
Hi All,

I have a HTML form to be fetched remotely and displayed within angular as native angular form. I need it to function like angular native form. I used "bypassSecurityTrustHtml" to sanitize HTML and display and it worked. But I am not able to submit form. I have included <form (ngSubmit)="OnSubmit(f)" #f="ngForm" AND < input [(ngModel)]="name" angular form tags but they are rename as ngsubmit, ngmodel as lowercase and I think this is the issue angular not recognizes form tags.

Angular sanitizer shows remotely loaded html form, but not renders it as form. Please advice me how can I handle this case.


Thanks,
Turkel.

Zlatko Đurić

unread,
Oct 1, 2017, 6:50:33 AM10/1/17
to Angular and AngularJS discussion
The problem is that such form (or anything you passed in via sanitizer) is outside of angular scope. Simply said, angular doesn't know about your form.

You could, after you pass the form in, try and attach your own listener to the form, but that's messy and probably buggy and has other problems too.

Better thing to do is to have that fetcher thing (which fetches the form) create a dynamic component. That's a bit more work but much better and easier to work with, once you grasp the concept.

Turkel

unread,
Oct 1, 2017, 7:19:09 AM10/1/17
to Angular and AngularJS discussion
Yes I agree, Angular not considers this form as part of page just showing it.
 Which type of dynamic component, what need to be function of this component?

Zlatko Đurić

unread,
Oct 1, 2017, 7:43:09 AM10/1/17
to Angular and AngularJS discussion


On Sunday, October 1, 2017 at 1:19:09 PM UTC+2, Turkel wrote:
Yes I agree, Angular not considers this form as part of page just showing it.
 Which type of dynamic component, what need to be function of this component?

Well, here's a pretty basic example. Your actual component (parent component), needs to use another, say "<lazy-form></lazy-form>" in the template. 

Now, this <lazy-form> component is just a normal angular component, but it has compiler, injector and ngModule injected, kind of like this:

import { Component, ComponentRef, Input, OnInit, ViewContainerRef, ViewChild, Compiler, Injector, NgModule, NgModuleRef } from '@angular/core';
import { SafeHtml, DomSanitizer } from '@angular/platform-browser';

@Component({
  selector: 'lazy-form',
  template: `<div #vc></div>`, // here's where you'll put your actual form
})
export class TaggedDescComponent {
  @ViewChild('vc', {read: ViewContainerRef}) vc: ViewContainerRef;
  @Input() someHTMLForm: string = ''; // this input is the actual form response you fetched from a remote endpoint.

  private cmpRef: ComponentRef<any>;

  constructor(private compiler: Compiler,
              private injector: Injector,
              private m: NgModuleRef<any>,
              private sanitizer: DomSanitizer) {
  }

  ngAfterViewInit() {
    const template = this.sanitizer.bypassSecurityTrustHtml(someHTMLForm);
    const styles = [`input { width: 100px }`]; // you can add styles like this here.

    // Now here I am creating a Component dinamically.
    const tmpCmp = Component({ template, styles })(class NestedFormComponent {});
    // MORE ON this later


    // Now that I have a component, I need to add it to a NgModule, also dynamic one.
    const tmpModule = NgModule({
      imports: [RouterModule],
      declarations: [tmpCmp]
    })(class {});

    // Now we compile it _on the fly_ and inject into that div up there in the template.
    this.compiler.compileModuleAndAllComponentsAsync(tmpModule)
      .then((factories) => {
        const f = factories.componentFactories[0];
        this.cmpRef = f.create(this.injector, [], null, this.m);
        this.cmpRef.instance.name = 'lazyForm';
        this.vc.insert(this.cmpRef.hostView);
      });
  }

  // cleanup
  ngOnDestroy() {
    if(this.cmpRef) {
      this.cmpRef.destroy();
    }
  }
}


So your actual component fetches the html, then renders lazy form like this: <lazy-form [someHTMLForm]="..."></lazy-form>.

Now, what you need to do is in your NestedFormComponent class, add whatever stuff you need to handle the form, like that onSubmit, but you should be able to pick up from here, hopefully.

Turkel

unread,
Oct 1, 2017, 3:00:04 PM10/1/17
to Angular and AngularJS discussion
After an hour of trying :D I got following error:

Argument of type '{ template: SafeHtml; styles: string[]; }' is not assignable to paramete
r of type
'Component'.
 
Types of property 'template' are incompatible.
   
Type 'SafeHtml' is not assignable to type 'string'.


Could you please see my html template and component, I have added all above code but somhow no luck:

Thank you for you time, I really appreciate.

Turkel

unread,
Oct 1, 2017, 3:01:24 PM10/1/17
to Angular and AngularJS discussion
The HTML which I m fetching is :

{"actions":"<label for=\"password\">Password<\/label>\r\n\t\t\t<input type=\"text\"\r\n id=\"password\"\r\n [(ngModel)]=\"password\"\r\n name=\"password\">"}

actions variable contains HTML for which linked within component.

Zlatko Đurić

unread,
Oct 1, 2017, 4:27:12 PM10/1/17
to ang...@googlegroups.com
Sorry, my mistake, typing that on a phone without checking.

You don't need sanitizer here. Put the "actions" prop directly into the template.


--
You received this message because you are subscribed to a topic in the Google Groups "Angular and AngularJS discussion" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/angular/ftz0lLIlrDA/unsubscribe.
To unsubscribe from this group and all its topics, send an email to angular+unsubscribe@googlegroups.com.
To post to this group, send email to ang...@googlegroups.com.
Visit this group at https://groups.google.com/group/angular.
For more options, visit https://groups.google.com/d/optout.

Turkel

unread,
Oct 2, 2017, 2:30:43 PM10/2/17
to Angular and AngularJS discussion
It is not generates forms but shows all source code of form. I have crated new project and removed all extra and added only remote fetcher of form. updated on pastebin. may be it is not compiles or bypasses this form :S I have tried all possible outcomes, change code on many ways no luck.

Turkel

unread,
Oct 2, 2017, 4:13:57 PM10/2/17
to Angular and AngularJS discussion
Code is updated, on my previous I havent binded compiled one into HTML. I am getting following error now:
Template parse errors:
There is no directive with "exportAs" set to "ngForm" ("<form (ngSubmit)="onSubmit(f)" [ERROR ->]#f="ngForm">
        <label for="password">Password</label>

I have imported FormsModule, ReactiveFormsModule into module.ts but seems like compiler not considers it.

Zlatko Đurić

unread,
Oct 2, 2017, 9:09:50 PM10/2/17
to Angular and AngularJS discussion

Well, you didn't add formsModule to your dynamic module :)

Try this: https://plnkr.co/edit/vEEQECofC7qfvCYCJ4bg?p=preview


Turkel

unread,
Oct 5, 2017, 3:59:47 PM10/5/17
to Angular and AngularJS discussion

Great it works perfectly now. After hours of tries I was able to combine code Router, Http and HTML Converter within one component.

You are great developer, i`d love to be your student :)

Thanks again,
Regards,
Turkel. 

Zlatko Đurić

unread,
Oct 6, 2017, 4:52:21 AM10/6/17
to Angular and AngularJS discussion

On Thursday, October 5, 2017 at 9:59:47 PM UTC+2, Turkel wrote:

Great it works perfectly now. After hours of tries I was able to combine code Router, Http and HTML Converter within one component.

You are great developer, i`d love to be your student :)


Thanks, I appreciate a good joke :)

Zlatko 

Turkel

unread,
Oct 8, 2017, 2:48:12 PM10/8/17
to Angular and AngularJS discussion
Hi Zlatko,

it is again me) I got another trouble, I want to know how can I call parent component functions within child component. Ex calling somefunction() from App through NestedFormComponent from your code above: https://plnkr.co/edit/vEEQECofC7qfvCYCJ4bg?p=preview

I want to update page when form posted and something changed on page by calling onsubmit action.

See my code line 50 and 77 components code: https://pastebin.com/xccH9X1X


Regards,
Turkel.

Zlatko Đurić

unread,
Oct 9, 2017, 2:31:25 AM10/9/17
to Angular and AngularJS discussion
Did you try injecting some common service into that dynamic module, and then communicate via that service?

Turkel

unread,
Oct 9, 2017, 2:47:10 AM10/9/17
to Angular and AngularJS discussion
Actually getPage() is my common service for to handle page generation. It have withCredentials:true parameter and data posting to handle cookie staff which is differs from other http services. I am not able to use "constructor(@Output() _paretnt: ParentComponent) {}" within "class NestedFormComponent" as I am getting error: "Decorators are not valid here" for "@"
Reply all
Reply to author
Forward
0 new messages