I have an Angular 6 app and am trying to display and submit a form that is generated from Django. I retrieve the form and display it using innerHtml. It shows up fine but when I click on the Submit button it doesn't call the function that I have attached to it. If I copy and paste the generated html then the submit button works fine (although I get a 403 response I think because of copying and pasting the CSRF token). Here is the code for my Angular component and template files and also the Django template:
login.component.html
<div *ngIf="!loggedIn; else successMessage" [innerHTML]="loginForm"></div>
<ng-template #successMessage>
Logged in
</ng-template>
login.component.ts
import { Component, Input, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
@Input() loggedIn: boolean;
id_username: string;
id_password: string;
loginForm: SafeHtml;
constructor(private router: Router, private httpClient: HttpClient, private sanitizer: DomSanitizer) {
}
ngOnInit() {
this.getLoginForm();
}
getLoginForm() {
this.httpClient.get('https://myserver/account/login/', { responseType: 'text' }).subscribe(res => {
this.loginForm = this.sanitizer.bypassSecurityTrustHtml(res);
console.log(this.loginForm);
});
}
login() {
console.log("Logging in user");
var response = this.httpClient.post('https://myserver.com/account/login/', {
id_username: this.id_username,
id_password: this.id_password
}).subscribe(res => {
this.loggedIn = true;
});
}
}
form.html Django template
{% extends "share/base.html" %}
{% block content %}
<div>
{% if form %}
{% if form.errors %}
<font color="red">{{ form.errors }}</font>
{% endif %}
<form #bdmForm="ngForm">
{% csrf_token %}
{% for field in form %}
<div class="form-group">
{{ field.label_tag }}
{{ field }}
</div>
{% endfor %}
<button type="button" class="btn btn-default" (click)="login()">Submit</button>
</form>
{% endif %}
</div>
{% endblock %}
forms.py (To include the fields) # -- coding: utf-8 -- from future import unicode_literals from django import forms
class Login(forms.Form):
username = forms.CharField(required=True, widget=forms.TextInput(attrs={'[(ngModel)]': 'id_username'}))
password = forms.CharField(required=True, widget=forms.PasswordInput(attrs={'[(ngModel)]': 'id_password'}))
I have also tried including the login() function using (ngSubmit)="login()"
in the form tag but that isn't working either.
I am relatively new to Angular and someone else is working on the Django side. I'm not sure if I just need to make a small change or if our whole approach is wrong but any input would be great!
I'd try to change the button to
<input type="submit" .... >
and then hook up with(submit)
on the element you bound with[innerHtml]
So basically I'd utilize event bubbling.But to be honest it's bad practice and you shouldn't receive html from your server in your Angular Component. Shortly speaking, you should design your form in Angular and send a POST HTTP Request and react to the response accordingly in your Angular Component.
If it's not possible I think the way to hook up to stuff in your innerHtml is via event bubbling or in runtime via referencing it through document.getElementBySomething and assigning callbacks to events.
Both of the ways feel kind of hacky