angular ngIf condition inside ngFor for to display like button - node.js

I'm working with angular buttons, To implement like button depends on ngif condition inside ngFor loop and i am getting the data from two MYSQL tables posts(post_id, user_id, description), likes(like_id, user_id, post_id, like_status). I joined the two table based on user_id,and i just ngIf implement the conditions depends on user_id & post_id & like_status.
I wrote these three conditions to show the button
*ngIf="( (postLikes.length != 0) && (post.user_id == like.user_id) && (post.post_id == like.post_id) && (like.like_status == 'like'))"
*ngIf="( (postLikes.length != 0) && (post.user_id == like.user_id) && (post.post_id == like.post_id) && (like.like_status == 'unlike'))"
*ngIf="( (postLikes.length == 0) && (post.user_id != like.user_id) && (post.post_id != like.post_id) && (like.like_status != 'unlike'))"
But first two conditions working fine but the last one not working if the user_id and post_id not present in a same row , so any one please correct the ngIf condition and help me.
<div class="container" style="width: 100%; height: 100%; ">
<div class="row" style=" margin: 1px; background-color: #fff; border: 2px solid #ada5a5; border-radius: 4px; ">
<!-- ngFor for posts -->
<div class="container" *ngFor="let post of posts; let i = index">
<div class="row" style="border-top: 2px solid #ada5a5;">
<div class="col-md-12 col-md-offset-0" style=" height: auto; ">
<h6> {{post.description}} </h6>
</div>
</div>
<!--ngFor for likes -->
<div class="container" style="border: 0px solid #ada5a5; ">
<div class="row">
<!--like button-->
<div class=" col-4">
<div *ngFor="let like of postLikes; let j = index ">
<div *ngIf="( (postLikes.length != 0) && (post.user_id == like.user_id) && (post.post_id == like.post_id) && (like.like_status == 'like'))">
<button type="button" class="btn btn-success" (click)=likeSubmit(post.user_id,post.post_id)>Like</button><p>liked</p>
</div>
<div *ngIf="( (postLikes.length != 0) && (post.user_id == like.user_id) && (post.post_id == like.post_id) && (like.like_status == 'unlike'))">
<button type="button" class="btn btn-danger" (click)=likeSubmit(post.user_id,post.post_id)>Like</button><p>Disliked</p>
</div>
<div
*ngIf="( (postLikes.length == 0) && (post.user_id != like.user_id) && (post.post_id != like.post_id) && (like.like_status != 'unlike'))">
<button type="button" class="btn btn-warning" (click)=likeSubmit(post.user_id,post.post_id)>Like</button><p>Default</p>
</div>
</div>
</div>
</div>
</div>
</div>
<TypeScript>
export class AppComponent {
title = 'my-app';
name = 'Angular';
posts: any[] =
[{"post_id":4,"user_id":2,"description":" Hi How are you ","created_date":"2019-01-28T12:30:49.000Z"},{"post_id":5,"user_id":2,"description":" Working a Fine ","created_date":"2019-01-28T12:31:20.000Z"},{"post_id":6,"user_id":2,"description":" Hi How are you ......","created_date":"2019-01-28T12:32:15.000Z"},{"post_id":7,"user_id":2,"description":" 4th test post","created_date":"2019-01-29T07:10:37.000Z"},{"post_id":9,"user_id":2,"description":" 5th test post","created_date":"2019-01-31T11:17:31.000Z"},{"post_id":10,"user_id":2,"description":" 6th test post","created_date":"2019-01-31T12:03:54.000Z"},{"post_id":11,"user_id":2,"description":" 7th post post","created_date":"2019-02-08T05:50:02.000Z"},{"post_id":12,"user_id":2,"description":" 8th test post ","created_date":"2019-02-08T06:08:01.000Z"}];
postLikes:any[] =[{"post_id":4,"user_id":2,"like_status":"unlike","like_id":10},{"post_id":5,"user_id":2,"like_status":"like","like_id":9},{"post_id":6,"user_id":2,"like_status":"like","like_id":8},{"post_id":7,"user_id":2,"like_status":"like","like_id":7},{"post_id":9,"user_id":2,"like_status":"like","like_id":11}]
post_id: any;
// likes: Like[];
like_id: number | null ;
like_status: string;
constructor(private http: HttpClient, private formBuilder: FormBuilder){
}
ngOnInit() { }
// Get user details from DB
getPosts(user_id) {
this.userService.getPosts(user_id).subscribe((data) => {
this.posts = data;
},
error => {
return console.log(error);
}
);
}
// join postlikes
getPostLikes(user_id) {
// debugger
this.userService.get_PostLikes(user_id).subscribe((results) => {
this.postLikes = results;
// console.log(results, 'results', this.postLikes, 'likes');
},
error => {
return console.log(error);
}
);
}
Once check my link for live code editing in stackBlitz
https://stackblitz.com/edit/angular-wddupe?file=src%2Fapp%2Fapp.component.html

It's not working because *ngIf="(postLikes.length == 0) ... will never evaluate to true inside your <div *ngFor="let like of postLikes; let j = index ">
If postLikes.length == 0 then the *ngFor does not complete any iterations of the template.
In fact, all of the postLikes.length logic is actually unnecessary here.

Related

Angular Reactive form Validation for dynamic forms inside *ngFor

I am new to angular when I was trying to put the form validation to the text field form was present inside *ngFor loop, So validation is working but it shows to every field but I want validation the particular field only , so please help me How to put the validation to the particular form field.
**HTML**
<div class="container" *ngFor="let post of posts; let i = index">
<div class="row">
<div class="col-md-12" style="display: block; ">
<form [formGroup]="commentForm" method="post" enctype="multipart/form-data" (ngSubmit)="comment_Submit(post.user_id, post.post_id,
commentForm)">
<div class="form-group">
<input type="text" class="form-control" name="comment{{i}}" formControlName="comment" id="comment"
placeholder="Enter comments" cols="40" rows="5" spellcheck="true"
style="width:100%; height: auto; border: 1px solid #ada5a5; border-radius: 4px; outline: none; user-select: text; white-space: pre-wrap; overflow-wrap: break-word; "
[ngClass]="{'form-control': true,
'is-invalid': !f.comment.valid,
'is-valid':f.comment.valid}">
<div *ngIf="f.comment.errors?.minlength && f.comment.touched" class="text-danger">Comment
should be at
least 2 characters.</div>
</div>
<button type="submit" class="btn-sm btn-success" [disabled]="!commentForm.valid">Comment</button>
</form>
</div>
</div>
</div>
**TypeScript**
export class PostsComponent implements OnInit {
get f() { return this.commentForm.controls; }
constructor(private userService: UserService, private formBuilder: FormBuilder,
private alerts: AlertsService) {
this.commentFormValidation();
}
commentForm: FormGroup;
ngOnInit() { }
commentFormValidation() {
this.commentForm = this.formBuilder.group({
comment: [null, [Validators.required, Validators.minLength(2)]]
});
}
Your posts all share the one and same form. If you have n amount of posts, you need n amount of forms. We can achieve this by creating an array (just a JS array) of formgroups, the same length that your posts array is...
formsArr = [];
constructor(private fb: FormBuilder) { }
ngOnInit() {
this.posts.forEach((x) => {
this.formsArr.push(this.fb.group({
comment: this.fb.control('', [Validators.required, Validators.minLength(2)])
}))
})
}
Then in your template you iterate formsArr. You probably need access to some stuff in your posts array... so we add the index in iteration, therefore you can access the specific post with posts[i]. Also remove method="post" from your form:
<div *ngFor="let a of formsArr; let i = index">
<form [formGroup]="a" (ngSubmit)="onSubmit(a.value, posts[i].user_id)">
<input formControlName="comment" />
<small *ngIf="a.hasError('minlength', 'comment') && a.get('comment').touched">
Needs to be 2 letters
</small>
<button type="submit" [disabled]="!a.valid">Comment</button>
</form>
</div>
StackBlitz

Angular 6 - Dynamic Search with HttpParams + Pagination

This is not a question. I am sharing the knowledge I gained after much research and testing. I built a search for optional fields using angle 6 and HttpParams. I am sharing this, because I searched a lot, not having been successful in the search.
Dev. Env.: Angular 6.0.9, Spring boot 2.0.7.
Form:
<form [formGroup]="searchForm" (ngSubmit)="submitSearch()">
<div class="row">
<div class="col-md-1">
<label>Código/Ano: </label>
</div>
<div class="col-md-2">
<input type="text" class="form-control form-control-sm" id="inputCodigo" formControlName="codigo" placeholder="código" maxlength="10">
</div>
<div class="col-md-1">
<input type="text" class="form-control form-control-sm" id="inputAno" formControlName="ano" placeholder="ano" maxlength="4">
</div>
<div class="col-md-1">
<label>Período: </label>
</div>
<div class="col-md-2">
<input type="text" class="form-control form-control-sm" placeholder="de" onfocus="(this.type = 'date')" formControlName="dataInicio">
</div>
<div class="col-md-2">
<input type="text" class="form-control form-control-sm" placeholder="ate" onfocus="(this.type = 'date')" formControlName="dataFinal">
</div>
<div class="col-md-1">
<input class="btn btn-primary btn-sm" type="submit" value="Buscar">
</div>
<div class="col-md-2">
<a [routerLink]="['/documentos/cadastro']" class="btn btn-sm btn-danger">Novo Documento</a>
</div>
</div>
Component:
export class DocumentosComponent implements OnInit {
documentos: Documento[];
searchForm: FormGroup;
docFiltro: DocumentoSearch = new DocumentoSearch();
constructor(
private documentoService: DocumentoService,
private fb: FormBuilder,
private page: Page
) {}
ngOnInit() {
this.page.page = "0";
this.createFormGroup();
this.getDocumentosByFilter();
}
getDocumentosByFilter() {
this.docFiltro = this.searchForm.value;
let searchParams = this.createSearchParam(this.docFiltro);
this.documentoService.findPage(searchParams).subscribe(
data => {
this.documentos = data["content"];
this.page.pages = new Array(data["totalPages"]);
},
error => {
console.log(error.error.message);
}
);
}
createSearchParam(docFiltro: DocumentoSearch): HttpParams {
let searchParams = new HttpParams()
searchParams = searchParams.set("page",this.page.page)
if (
docFiltro.codigo != null &&
docFiltro.codigo != undefined &&
docFiltro.codigo != ""
) {
searchParams = searchParams.set("codigo", docFiltro.codigo);
}
if (
docFiltro.ano != null &&
docFiltro.ano != undefined &&
docFiltro.ano != ""
) {
searchParams = searchParams.set("ano", docFiltro.ano);
}
if (
docFiltro.dataInicio != null &&
docFiltro.dataInicio != undefined &&
docFiltro.dataInicio != ""
) {
searchParams = searchParams.set("dataInicio", docFiltro.dataInicio);
}
if (
docFiltro.dataFinal != null &&
docFiltro.dataFinal != undefined &&
docFiltro.dataFinal != ""
) {
searchParams = searchParams.set("dataFinal", docFiltro.dataFinal);
}
return searchParams;
}
setPage(i, event: any) {
event.preventDefault();
this.page.page = i;
this.getDocumentosByFilter();
}
createFormGroup() {
this.searchForm = this.fb.group({
codigo: [""],
ano: [""],
dataInicio: [""],
dataFinal: [""]
});
}
submitSearch() {
this.page.page = '0';
this.getDocumentosByFilter();
}
}
Service method:
findPage(searchParams: HttpParams) {
return this.http.get<Documento[]>(`${API_URL}/sge/documento/search`, {params: searchParams});
}

How to clear all the md-input fields at once inside a md-form using an external button in Angular 2/2+/4

I want to clear all the fields inside a md-form at once using an external clear button like you do in normal HTML Forms. The problem with md-form is that it contains md-input fields instead of regular input fields. So the simple reset function won't trigger that.
I've set the type of each field to 'search' that gives some kind of control but it's like u have to manually click and remove each value of the filed. I want to erase them all at once.
Is there a proper way to to this?
Thanks in advance.
Form Code
<form class="formwidth" (ngSubmit)="searchClass()" #myForm="ngForm">
<table class="fullwidth" cellspacing="0">
<tr>
<td>
</td>
<td>
<md-input-container div="addClassName" *ngIf="classClicked === true">
<input [(ngModel)]="message.className" mdInput placeholder="Class Name" id="className" name="classname" type="search" >
</md-input-container>
<md-input-container div="addJarName" *ngIf="jarFileClicked === true">
<input [(ngModel)]="message.jarName" mdInput placeholder="Jar File Name" id="jarName" name="jarname" type="search" >
</md-input-container>
<md-input-container div="addVersion" *ngIf="versionClicked === true">
<input [(ngModel)]="message.version" mdInput placeholder="Version" id="versionNumber" name="versionnumber" type="search" >
</md-input-container>
<md-input-container div="addDirectory" *ngIf="directoryClicked === true">
<input [(ngModel)]="message.directory" mdInput placeholder="Directory" id="directoryName" name="directoryname" type="search" >
</md-input-container>
<md-input-container div="addDependentClass" *ngIf="dependentClicked === true">
<input [(ngModel)]="message.dependentClass" mdInput placeholder="Dependent Class Name" id="dependentClassName" name="dependentclassname" type="search" >
</md-input-container>
</td>
</table>
<br>
<p *ngIf="classClicked === true || jarFileClicked === true || versionClicked === true || directoryClicked === true || dependentClicked === true">
<button md-raised-button color="accent" type="submit" id="submitButton">Submit</button>
<button md-raised-button id="clearButton" (click)="setAllToFalse() && clearFields()">Clear</button>
</p>
</form>
P.S : I tried something like this with typescript as well. But it don't work
clearFields(){
this.message.jarName="";
this.message.className="";
this.message.version="";
this.message.directory="";
this.message.dependentClass="";
}
Simply calling the clearFields() method inside another method worked.
setAllToFalse(){
this.classClicked = false;
this.jarFileClicked = false;
this.versionClicked = false;
this.directoryClicked = false;
this.dependentClicked = false;
this.condition_1 = false;
this.condition_2 = false;
this.condition_3 = false;
this.condition_4 = false;
this.condition_5 = false;
this.condition_6 = false;
this.condition_7 = false;
this.clearFields();
}

How can assign a default value for Html.EditorFor in js function

This is my View..
<div style="float: left; width: 450px; text-align:left; margin-left:80px">
<div class="row">
<div class="label" style="float: left; width: 80px">Date From: </div>
<div class="control">
#Html.EditorFor(model => model.DateFrom, new { ID = "datefrom" })
#Html.ValidationMessageFor(model => model.DateFrom, null, new { style = "color: red" })
</div>
</div>
<div class="row">
<div class="label" style="float: left; width: 80px">Date To: </div>
<div class="control" >
#Html.EditorFor(model => model.DateTo, new { ID = "dateto" })
#Html.ValidationMessageFor(model => model.DateTo, null, new { style = "color: red" })
</div>
</div>
<div><input type="checkbox" id="relative" name="relative" onclick="validate()" />Is Relative</div>
</div>
And this is my js function:
function validate() {
if (document.getElementById('relative').checked) {
document.getElementById('#Html.IdFor(model => model.DateFrom)').disabled = true;
document.getElementById('#Html.EditorFor(model => model.DateFrom, new { #Value = DateTime.Now })');
document.getElementById('#Html.IdFor(model => model.DateTo)').disabled = true;
document.getElementById('#Html.EditorFor(model => model.DateTo, new { #Value = DateTime.Now })');
} else {
document.getElementById('#Html.IdFor(model => model.DateFrom)').disabled = false;
document.getElementById('#Html.IdFor(model => model.DateTo)').disabled = false;
}
}
How can assign a default value (DateTiem.Now) to Html.EditorFor? Thanks a lot for your Help!!!
No Body has replied to this question in a long time. If somebody else trying to solve the similar issue.
try this in your Javascript.
document.getElementById('#Html.IdFor(model => model.Draw)')

How can I dynamically create rows in Jade?

Right now I have this:
- count = 0
- each organization in organizations
if (count == 0 || count % 3 == 0)
.row
.col-md-4
a(href="#{organization.url}" target="_blank")
.fancyy-box
h3= organization.name
img(src="/images/organizations/#{organization.logo}")
p= organization.mission
- count = count + 1
What I am trying to do is start a new row every third organization, so that I get:
<div class="row">
<div class="organization">...</div>
<div class="organization">...</div>
<div class="organization">...</div>
</div>
<div class="row">
<div class="organization">...</div>
<div class="organization">...</div>
<div class="organization">...</div>
</div>
// and so on...
Right now I am getteing:
<div class="row" />
<div class="organization">...</div>
<div class="organization">...</div>
<div class="organization">...</div>
<div class="row" />
<div class="organization">...</div>
<div class="organization">...</div>
<div class="organization">...</div>
<div class="row" />
Is there an easy way to accomplish this?
Like Mukesh Soni said you need to think about your indentation. But this is just one part of your problem, the second thing I recognized is your conditional statement and your loop. I edited this a little bit like you can see below:
- for (var j = 0; j < organizations.length; j++)
if (j == 0 || j % 3 == 0)
.row
- for (var i = j; i < (3 + j); i++ )
- if (i >= organizations.length) break;
.col-md-4
a(href="#{organizations[i].url}" target="_blank")
.fancyy-box
h3= organizations[i].name
img(src="/images/organizations/#{organizations[i].logo}")
p= organizations[i].mission
So in the first for loop I simply post a row every three times of iteration, in the second for loop I add your data, simply by adding 3 lines / divs. If i gets bigger then your data - it breaks.
Here an example: first my data
{
organizations: [
{name: 'demo1', url: 'example.com', logo: 'pic1.jpg', mission: '1'},
{name: 'demo2', url: 'anotherexample.com', logo: 'pic2.jpg', mission: '2'},
{name: 'demo3', url: 'justanotherexample.com', logo: 'pic3.jpg', mission: '3'},
{name: 'demo4', url: 'wowjustanotherexample.com', logo: 'pic4.jpg', mission: '4'}]
}
Now the HTML output:
<div class="row">
<div class="col-md-4">
<a href="example.com" target="_blank">
<div class="fancyy-box">
<h3>demo1</h3><img src="/images/organizations/pic1.jpg"/>
<p>1</p>
</div>
</a>
</div>
<div class="col-md-4">
<a href="anotherexample.com" target="_blank">
<div class="fancyy-box">
<h3>demo2</h3><img src="/images/organizations/pic2.jpg"/>
<p>2</p>
</div>
</a>
</div>
<div class="col-md-4">
<a href="justanotherexample.com" target="_blank">
<div class="fancyy-box">
<h3>demo3</h3><img src="/images/organizations/pic3.jpg"/>
<p>3</p>
</div>
</a>
</div>
</div>
<div class="row">
<div class="col-md-4">
<a href="wowjustanotherexample.com" target="_blank">
<div class="fancyy-box">
<h3>demo4</h3><img src="/images/organizations/pic4.jpg"/>
<p>4</p>
</div>
</a>
</div>
</div>
You could do this
.row
each organization, i in organizations
if i > 0 && i % 3 === 0
// jade/pug can interpret html
</div><div class="row">
// past you col template here
.col-md-4
a(href="#{organizations[i].url}" target="_blank")
.fancyy-box
...

Resources