I have this collection in "results.component.ts": results: Result[]
I would like to iterate over the collection, displaying each result.
I would like to have a seperate component for this called result.component.ts. This is because a result could get complex and large.
What I have so far is not displaying anything. The output html has some commented out template bindings:
<div _ngcontent-fud-12="" class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-xl-4
offset-xl-4">
<!--template bindings={
"ng-reflect-ng-for-of": "[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]"
}--><!--template bindings={}--><!--template bindings={}--><!--template bindings={}--><!--template bindings={}--><!--template bindings={}--><!--template bindings={}--><!--template bindings={}--><!--template bindings={}--><!--template bindings={}--><!--template bindings={}-->
</div>
Here is my relevant code:
results.component.html:
<div id="results" class="text-uppercase">
<div id="up-button-row" class="row">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-xl-4
offset-xl-4">
<button class="m-x-auto" md-fab [disableRipple]="true" (click)="scrollUp()"></button>
</div>
</div>
<div class="row" *ngIf="noResults">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-xl-4
offset-xl-4">
<h2 class="m-x-auto">No vegan stuff found :-(</h2>
</div>
</div>
<div class="row" *ngIf="!noResults">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-xl-4
offset-xl-4">
<div *ngFor="let result of results"><result></result></div>
</div>
</div>
</div>
results.component.ts:
import { Component, AfterViewInit } from '#angular/core';
import { ResultComponent } from './result.component';
import { Result } from '../result'
#Component({
selector: 'results-div',
templateUrl: 'app/find-page/results.component.html',
styleUrls: ['app/find-page/results.component.css' ],
directives:[ResultComponent]
})
export class ResultsComponent implements AfterViewInit {
results: Result[];
noResults: boolean;
ngAfterViewInit() {
this.scrollDown();
}
scrollDown() {
ScrollToAnchor.goToTargetBottom("#results");
}
scrollUp() {
ScrollToAnchor.goToTarget("#find-page");
}
}
result.component.html:
<div class="col-sm-6 col-lg-2" style="margin-top:20px; padding: 25px;">
<div class="product-item scale-on-hover" (click)="setCurrentlySelectedProduct()">
<div [ngStyle]="{background: result.imagePath}" id="image"></div>
<div id="info">
<h6 id="brand" class="medium-text">{{brand}}</h6>
<h6 id="name" class="medium-text">{{name}}</h6>
</div>
</div>
</div>
result.component.ts:
import { Component, AfterViewInit } from '#angular/core';
import { Result } from '../result';
#Component({
selector: 'result',
templateUrl: 'app/find-page/result.component.html',
styleUrls: ['app/find-page/result.component.css' ]
})
export class ResultComponent{}
How do I pass the result data for 1 result from results.component to result.component.
How do I get the result.component.html to display once for each result?
#Component({
selector: 'result',
templateUrl: 'app/find-page/result.component.html',
styleUrls: ['app/find-page/result.component.css' ]
})
export class ResultComponent{
#Input() result;
}
<div *ngFor="let result of results"><result [result]="result"></result></div>
<div class="col-sm-6 col-lg-2" style="margin-top:20px; padding: 25px;">
<div class="product-item scale-on-hover" (click)="setCurrentlySelectedProduct()">
<div [ngStyle]="{background: result.imagePath}" id="image"></div>
<div id="info">
<h6 id="brand" class="medium-text">{{result.brand}}</h6>
<h6 id="name" class="medium-text">{{result.name}}</h6>
</div>
</div>
</div>
Related
I am trying to create password reset api using Django Rest Framework and Angular 6. But when I try to do POST call to the password reset url I am receiving error saying "CSRF verification failed. Request aborted"
my url.py file includes:
url(r'password-reset/', auth_views.PasswordResetView.as_view()),
url(r'password-reset/done/', auth_views.PasswordResetDoneView.as_view()),
url(r'password-reset-confirm/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view()),
url(r'password_reset_complete/',auth_views.PasswordResetCompleteView.as_view())
For the front end I am using Angular as follows:
my forgot-password.html includes:
<navbar></navbar>
<div class="container-fluid px-xl-5">
<section class="py-5">
<div class="row">
<div class="col-lg-12 mb-5">
<div class="card">
<div class="card-header" style="text-align: center;">
<h3 class="h6 text-uppercase mb-0">RESET PASSWORD FORM</h3>
</div>
<div class="card-body">
<form class="form-horizontal" #forgotPassword="ngForm">
<div class="form-group row">
<label class="col-md-3 form-control-label">Email Address</label>
<div class="col-md-6">
<input class="validate" #email="ngModel" [(ngModel)]="input.email" name= "email" type="email" placeholder="Email Address" class="form-control" [pattern]="emailpattern" required>
<div class="alert alert-danger" *ngIf="email.touched && !email.valid">Email is required!</div>
</div>
</div>
<div class="line"></div>
<div class="alert alert-success" *ngIf="successMessage">{{ successMessage }}</div>
<div class="alert alert-danger" *ngIf="errorMessage">{{ errorMessage }}</div>
<div class="form-group row">
<label class="col-md-3 form-control-label"><a routerLink="/login">Back to Login</a></label>
<div class="col-md-12" style="text-align: center;">
<button (click)="submitEmail()" type="submit" class="btn btn-primary shadow" [disabled]="!forgotPassword.valid">Send Reset Link</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</section>
</div>
and forgot-password.ts file is as follow:
import { Component, OnInit } from '#angular/core';
import { UsersService } from 'src/app/services/users.service';
#Component({
selector: 'app-forgot-password',
templateUrl: './forgot-password.component.html',
styleUrls: ['./forgot-password.component.scss'],
providers: [UsersService]
})
export class ForgotPasswordComponent implements OnInit {
input;
emailpattern = "[a-z0 - 9!#$%& '*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&' * +/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?";
errorMessage: string = '';
successMessage: string = '';
constructor(private userService: UsersService) { }
ngOnInit() {
this.input = {
email: ''
};
}
submitEmail() {
this.successMessage = '';
this.errorMessage = '';
this.userService.resetPassword(this.input).subscribe(
response => {
this.successMessage = 'Please Check you mail for password reset link!';
},
error => this.errorMessage = 'Please enter correct email or try again later!'
);
}
}
and finally .service is as follows:
resetPassword(data): Observable<any> {
return this.http.post('http://127.0.0.1:8000/api/password-reset/', data);
}
I am not able to understand what to do and how to solve this issue.
CSRF are usually used if session authentication. SPAs don't use this kind of auth (usually it's used another pattern such as JSON web tokens). You can disable CSRF in the Django as explained here: Django Rest Framework remove csrf
I've been trying to create a DRF API with an Angular front end for an existing project that I have. I've created a serializer for User and Device. I tried removing multiple pieces of the HTML component, managing to result in a different error, StaticInjectorError(AppModule -> DevicePostService).
I'm still pretty new to Angular so what it seems like the error is coming from is the fact that my devicepostservice is not getting served to the web page for some reason.
Console error:
[Error] Error: Template parse errors:
Unexpected character "<" ("
<div class="col-sm-4">
<button (click)="login()" class="btn btn-primary">Log In</button
[ERROR ->]</div>
<div class="col-sm-12">
<span *ngFor="let error of _userService.errors.non_field_errors""): ng:///AppModule/AppComponent.html#15:2
Unexpected closing tag "div". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags ("
<div class="col-sm-4">
<button (click)="login()" class="btn btn-primary">Log In</button
[ERROR ->]</div>
<div class="col-sm-12">
<span *ngFor="let error of _userService.errors.non_field_errors""): ng:///AppModule/AppComponent.html#15:2
Unexpected closing tag "div". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags (" <span *ngFor="let error of _userService.errors.non_field_errors">{{ error }}<br /></span>
</div>
[ERROR ->]</div>
<div class="row" *ngIf="_userService.token">
<div class="col-sm-12">You are logged in as {{ "): ng:///AppModule/AppComponent.html#19:0
_preparseLoadedTemplate (vendor.js:24658)
normalizeTemplate (vendor.js:24635)
loadDirectiveMetadata (vendor.js:26827)
(anonymous function) (vendor.js:34471)
forEach
(anonymous function) (vendor.js:34470)
forEach
_loadModules (vendor.js:34467:83)
_compileModuleAndComponents (vendor.js:34445)
compileModuleAsync (vendor.js:34405)
bootstrapModule (vendor.js:53721)
./src/main.ts (main.js:326:116)
__webpack_require__ (runtime.js:79)
(anonymous function) (main.js:339)
__webpack_require__ (runtime.js:79)
checkDeferredModules (runtime.js:46)
webpackJsonpCallback (runtime.js:33)
Global Code (main.js:1)
App.component.html
<h2>Log In</h2>
<div class="row" *ngIf="!_userService.token">
<div class="col-sm-4">
<label>Username:</label><br />
<input type="text" name="login-username" [(ngModel)]="user.username">
<span *ngFor="let error of _userService.errors.username"><br />
{{ error }}</span></div>
<div class="col-sm-4">
<label>Password:</label><br />
<input type="password" name="login-password" [(ngModel)]="user.password">
<span *ngFor="let error of _userService.errors.password"><br />
{{ error }}</span>
</div>
<div class="col-sm-12">
<span *ngFor="let error of _userService.errors.non_field_errors">{{ error }}<br /></span>
</div>
</div>
<div class="row" *ngIf="_userService.token">
<div class="col-sm-12">You are logged in as {{ _userService.username }}.<br />
Token Expires: {{ _userService.token_expires }}<br />
<button (click)="refreshToken()" class="btn btn-primary">Refresh Token</button>
<button (click)="logout()" class="btn btn-primary">Log Out</button>
</div>
</div>
<!--
<h2 class="mt-3">Devices</h2>
<div *ngFor="let device of devices">
<div class="row mb-3">
<label class="col-md-2">Owner:</label>
<div class="col-md-2 mb-1">{{ device.owner }}</div>
<label class="col-md-2">Brand:</label>
<div class="col-md-6">{{ device.brand }}</div>
<div class="col-md-12">{{ device.name }}</div>
</div>
</div>-->
App.component.ts
import {Component, OnInit} from '#angular/core';
import {DevicePostService} from './device_post.service';
import {UserService} from './user.service';
import {throwError} from 'rxjs';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
/**
* An object representing the user for the login form
*/
public user: any;
public devices;
public new_device: any;
constructor(private _devicePostService: DevicePostService, private _userService: UserService) { }
ngOnInit() {
this.getDevices();
this.new_device = {};
this.user = {
username: '',
password: ''
};
}
getDevices() {
this._devicePostService.list().subscribe(
data => {
this.devices = data;
},
err => console.error(err),
() => console.log('done loading devices')
)
}
updateDevice () {
this._devicePostService.create(this.new_device, this.user.token).subscribe(
data => {
this.getDevices();
return true;
},
error => {
console.error('Error saving!');
return throwError(error);
}
);
}
login() {
this._userService.login({'username': this.user.username, 'password': this.user.password});
}
refreshToken() {
this._userService.refreshToken();
}
logout() {
this._userService.logout();
}
}
Seems like you have a basic syntax error in your template
<button (click)="login()" class="btn btn-primary">Log In</button
should be
<button (click)="login()" class="btn btn-primary">Log In</button>
(note the final '>' character)
I have a Web Service which is providing some user data (this is Java backend) and I have an Angular component:
import { Component,state,style,animate,transition, trigger, keyframes,
OnInit } from '#angular/core';
import { ActivatedRoute } from '#angular/router';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/pluck';
import { IUser } from './user.interface';
#Component({
moduleId: module.id,
selector: 'user-cmp',
templateUrl: 'user.component.html'
})
export class UserComponent {
user: Observable<IUser>;
errorMessage: string;
constructor(private _userService: ActivatedRoute){
this.user = _userService.data.pluck('user');
}
}
I am using a Resolver:
import { Resolve } from '#angular/router';
import { Observable } from 'rxjs/Observable'
import { Observer } from 'rxjs/Observer';
import { IUser } from './user.interface';
import { UserService } from './user.service';
import {Injectable} from "#angular/core";
#Injectable()
export class UsersResolver implements Resolve<IUser> {
constructor (private _userService: UserService) {}
resolve(): Observable<IUser>{
return this._userService.getUser();
}
}
Resolver is using a service:
import {Injectable} from "#angular/core";
import { Http, Response } from "#angular/http";
import { IUser } from './user.interface';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
#Injectable()
export class UserService {
private _userUrl = 'http://localhost:8000/rest/users';
constructor(private _http: Http){
}
getUser(): Observable<IUser>{
return this._http.get(this._userUrl)
.map((response: Response) => {
return <IUser> response.json();
})
.do(data => console.log('All: ' + JSON.stringify(data)))
.catch(this.handleError);
}
private handleError (error: Response){
console.error(error);
return Observable.throw(error.json().error || 'Server Error');
}
}
And finally the View:
<div class="main-content" >
<div class="container-fluid">
<div class="row">
<div class="col-md-8">
<div class="card" [#carduserprofile]>
<div class="header">
<h4 class="title">Edit User Profile</h4>
</div>
<div *ngIf="user" class="content">
<form>
<div class="row">
<div class="col-md-3">
<div class="form-group">
<label>Username</label>
<input type="text" class="form-control" placeholder="Username" value="{{user.username }}">
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label>Email address</label>
<input type="email" class="form-control" placeholder="Email" value="{{user.password}}">
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label>Phone</label>
<input type="text" class="form-control" placeholder="Phone" value="{{user.telephone}}">
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label>Type</label>
<input type="text" class="form-control" disabled placeholder="User type" value="{{user.type}}">
</div>
</div>
</div>
<button type="submit" class="btn btn-info btn-fill pull-right">Update Profile</button>
<div class="clearfix"></div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
The module looks like this:
import { NgModule } from '#angular/core';
import { RouterModule } from '#angular/router';
import { BrowserModule } from '#angular/platform-browser';
import { MODULE_COMPONENTS, MODULE_ROUTES } from './dashboard.routes';
import { UsersResolver } from './user/user.resolver';
#NgModule({
imports: [
BrowserModule,
RouterModule.forChild(MODULE_ROUTES)
],
declarations: [ MODULE_COMPONENTS ],
providers: [ UsersResolver ]
})
export class DashboardModule{}
And also the part of the route is like this:
{ path: 'user', component: UserComponent, resolve: {user: UsersResolver} },
I didn't paste some useless parts of the code, like animations and etc.
My problem is, it prints the data from the webservide using the .do in the service, but it doesn't show nothing in the View. Fields are blank.
I am using *ngIf in case of blank user data from WS.
I have no idea why and also I don't know how to implement some codes to check it in the View.
Any help will be great!
Thanks in advance.
The problem I see is located here:
constructor(private _userService: ActivatedRoute){
this.user = _userService.data.pluck('user');
}
this.user is an observable so you need to subscribe it to get the value either within the component (with this.user.subscribe(...)) or in the template using the async pipe.
Perhaps you could simply leverage the snapshot for the route:
constructor(private _userService: ActivatedRoute){
this.user = _userService.snapshot.data['user'];
}
This way the user would be a raw JS object and not an observable. So using the following should be better:
<div *ngIf="user" class="content">
I have a problem with google geocode suggest. I have a modal which show a form to complete an address. I have implemented geocode to make easier the address filling, but the suggest is appearing behind the modal, like this:
Some code over here:
JS which implements geocode:
GoogleGeocode = (function () {
var _api = {};
var _googleApiRetrievedOk = false;
var _autocompleteEvent;
var _addressInputId, _zipCodeInputId, _countryInputId, _countryComboboxId;
var _componentToRetrieve = {
street_number: 'short_name',
route: 'long_name',
locality: 'long_name',
administrative_area_level_1: 'short_name',
country: 'long_name',
postal_code: 'short_name'
};
function loadGoogleApis() {
// Importar fuentes
$('head').append($('<link rel="stylesheet" type="text/css" />').attr('href', 'https://fonts.googleapis.com/css?family=Roboto:300,400,500'));
// Importar api Places
$('head').append($('<script type="text/javascript" />').attr('src', 'https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true&libraries=places&callback=GoogleGeocode.GoogleGeocodeInit'));
}
function googleGeocodeInit() {
_googleApiRetrievedOk = true;
}
$(document).ready(loadGoogleApis);
return _api;
})();
View which supports modal:
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-footer">
<div class="col-md-6 col-md-offset-1">
<h2>#T("StudentData")</h2>
</div>
<button type="button" class="btn btn-CTA" data-dismiss="modal">X</button>
</div>
<div class="modal-header">
#Html.Action("PrepareStudentDataModel", "Topic")
</div>
</div>
Part of view which calls google geocode:
<div class="form-group row">
<div class="col-md-12">
#Html.TextAreaFor(model => model.Address1, new { #class = "form-control", placeholder = #T("wke.checkout.StudentAddress.geocodeaddress") })
#Html.ValidationMessageFor(model => model.Address1)
<span class="col-md-6 col-xs-6 field-validation-valid" id="StudentAddress_address1MessageValidation" style="visibility: hidden;">
#T("wke.checkout.StudentAddress.messagevalidation")
</span>
</div>
</div>
I have a simple contact form, with validation done using ember-cp-validations https://github.com/offirgolan/ember-cp-validations and I now need to integrate the new Google Recaptcha into that.
For the rendering of the recaptcha, I am using this code - https://gist.github.com/cravindra/5beeb0098dda657433ed - which works perfectly.
However, I don't know how to deal with the verification process to allow the form to be submitted/prevented if the challenge is correct/incorrect or not provided
Here is a truncated version of my contact-form component
import Ember from 'ember';
import Validations from './cp-validations/contact-form';
import config from '../config/environment';
export default Ember.Component.extend(Validations,{
data:{},
nameMessage:null,
init() {
this._super(...arguments);
this.set('data',{});
},
actions:{
submitForm() {
this.validate().then(({model,validations}) => {
if (validations.get('isValid')) {
// submit form
}
else {
if(model.get('validations.attrs.data.name.isInvalid')){
this.set('nameMessage',model.get('validations.attrs.data.name.messages'));
}
}
})
}
}
});
Here is the template for the component, which includes the rendering of the recpatcha using the gist above
<form {{action 'submitForm' on='submit'}}>
<div class="row">
<div class="medium-6 columns">
{{input type="text" value=data.name id="name" placeholder="Enter your name"}}
<div class="error-message">
{{nameMessage}}
</div>
</div>
</div>
<div class="row">
<div class="medium-12 columns">
{{google-recaptcha}}
</div>
</div>
<button class="button primary" type="submit">Submit</button>
</form>
The Validations import looks like this
import { validator, buildValidations } from 'ember-cp-validations';
export default buildValidations({
'data.name': {
validators: [
validator('presence',{
presence:true,
message:'Please enter your name'
})
]
},
});
Many thanks for any help!
Register captchaComplete in your google-recaptcha component and mix the answer with your validations
UPDATE
contact-form.hbs
<form {{action 'submitForm' on='submit'}}>
<div class="row">
<div class="medium-6 columns">
{{input type="text" value=data.name id="name" placeholder="Enter your name"}}
<div class="error-message">
{{nameMessage}}
</div>
</div>
</div>
<div class="row">
<div class="medium-12 columns">
{{google-recaptcha captchaComplete=validateRecatcha}}
</div>
</div>
<button class="button primary" type="submit">Submit</button>
</form>
contact-form.js
import Ember from 'ember';
import Validations from './cp-validations/contact-form';
import config from '../config/environment';
export default Ember.Component.extend(Validations,{
data:{},
nameMessage:null,
captchaValidated: false,
init() {
this._super(...arguments);
this.set('data',{});
},
actions:{
validateRecatcha(data){
//if data denotes captcha is verified set captchaValidated to true else false
},
submitForm() {
this.validate().then(({model,validations}) => {
if (validations.get('isValid') && this.get('captchaValidated')) {
// submit form
}
else {
if(model.get('validations.attrs.data.name.isInvalid')){
this.set('nameMessage',model.get('validations.attrs.data.name.messages'));
}
}
})
}
}
});