My objective is when the user clicks a message displayed on /messages, it redirects them to /message with the messages displayed information. Please direct me in the right direction if I'm doing something wrong.
This is my error:
Unhandled Promise rejection: Template parse errors:
Can't bind to 'messages' since it isn't a known property of 'message'. ("ge-header">{{user.name}}</h2>
<ul class="list-group" style="list-style-type: none;">
<message [ERROR ->][messages]="message"></message>
Inbox: <ul class="list-group" style="list-style-type: none;">
"): MessagesComponent#3:13
'message' is not a known element:
1. If 'message' is an Angular component, then verify that it is part of this module.
2. If 'message' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '#NgModule.schemas' of this component to suppress this message. ("class="page-header">{{user.name}}</h2>
<ul class="list-group" style="list-style-type: none;">
[ERROR ->]<message [messages]="message"></message>
Inbox: <ul class="list-group" style="list-style-type: no"): MessagesComponent#3:4 ; Zone: <root> ; Task: Promise.then ; Value:
Messages Component:
import { Component, OnInit } from '#angular/core';
import { AuthService } from '../../services/auth.service';
import { Router } from '#angular/router';
#Component({
selector: 'app-messages',
templateUrl: './messages.component.html',
styleUrls: ['./messages.component.css']
})
export class MessagesComponent implements OnInit {
messages: Object;
username: String;
user: Object;
messageID: String;
public UserList: Object;
public RecpList: Object;
constructor(private authService: AuthService,
private router: Router
) { }
ngOnInit() {
this.authService.getProfile().subscribe(profile => {
this.user = profile.user;
this.username = profile.user.username;
},
err => {
console.log(err);
return false;
});
this.authService.getMessages(this.username).subscribe(list => {
this.UserList = list.UserList;
this.RecpList = list.RecpList;
},
err => {
console.log(err);
return false;
});
}
onMessageClick(messageID){
this.authService.getMessage(this.user, messageID).subscribe(list => {
console.log(list);
this.router.navigate(['/message', ]);
});
}
}
Messages html:
<div *ngIf="user">
<h2 class="page-header">{{user.name}}</h2>
<ul class="list-group" style="list-style-type: none;">
<message [messages]="message"></message>
Inbox: <ul class="list-group" style="list-style-type: none;">
<li *ngFor="let message of RecpList" (click)="onMessageClick(message.messageID)" class="list-group" style="text-align: center;"><strong>{{message.createdBy}}</strong> {{message.subject}} <strong>{{message.dateCreated}}</strong></li>
</ul>
Sent: <ul class="list-group" style="list-style-type: none;">
<li *ngFor="let message of UserList" (click)="onMessageClick(message.messageID)" class="list-group" style="text-align: center;"><strong>{{message.recipients}}</strong> {{message.subject}} <strong>{{message.dateCreated}}</strong></li>
</ul>
<li class="list-group"><a [routerLink] = "['/newmessage']">New Message</a></li>
</ul>
</div>
Message Component:
import { Component, OnInit } from '#angular/core';
import { AuthService } from '../../services/auth.service';
import { Router } from '#angular/router';
#Component({
selector: 'app-message',
templateUrl: './message.component.html',
styleUrls: ['./message.component.css'],
inputs: ['messages']
})
export class MessageComponent implements OnInit {
messages: Object;
user: Object;
createdBy: String;
recipients: String;
subject: String;
message: String;
previousMessage: String;
nextMessage: String;
constructor(private authService: AuthService,
private router: Router) { }
ngOnInit() {
this.authService.getProfile().subscribe(profile => {
this.user = profile.user;
},
err => {
console.log(err);
return false;
});
}
}
Message html:
<p>{{messages.subject}}</p>
This is my component structure
So it looks like a couple of things:
You need to include the id or message in here this.router.navigate(['/message', ]); which is looks like you may have missed adding it in there
You need to specify the path in your router like this { path: 'message/:id', component: MessageComponent }
You can retrieve what is passed in by getting it from the params using something like this:
this.message = this.route.params.subscribe(params => {
this.id = params['id'];
});
Related
I am pretty new with mongoose & node.js and I am having an issue with displaying my users messages privately.
The message recipient, sender and message content is stored in the database.
but when I want to see the message's between two users, the messages between two users are displayed on every user messages tab!.
(developing in MEAN stack environment)
The Problem: https://i.imgur.com/qfDlMml.mp4
Messages Schema:
var messageSchema = new mongoose.Schema({
id: {
type: Number,
},
senderId: {
type: Number
},
senderUsername: {
type: String
},
recipientId: {
type: Number
},
recipientUsername: {
type: String
},
content: {
type: String,
required:true
},
dateRead: {
type: Date
},
messageSent: {
type: Date
},
senderDeleted: {
type: Boolean
},
recipientDeleted: {
type: Boolean
}
},
{
collection: 'messages',
timestamps: true
},
);
module.exports = mongoose.model('Messages', messageSchema)
User route:
//Get Message Of User
usersRoute.route("/messages/thread/:username/:senderUsername").get((req, res) => {
Messages.find(({ data: { "$in" : [req.params.senderUsername,req.params.username]} }, (error, data) => {
if (error) {
console.log(error)
throw error;
}
res.json(data);
}))
})
messages.service:
getMessageThread(username: string,sender:string) {
return this.http.get<Message[]>(`${AUTH_API}messages/thread/${username}/${sender}`);
}
member-messages.ts:
import { Component, OnInit, Input } from '#angular/core';
import { NgForm } from '#angular/forms';
import { Message } from 'src/app/models/message';
import { User } from 'src/app/models/user';
import { AccountService } from 'src/app/services/account.service';
import { MessageService } from 'src/app/services/message.service';
import { Observable, take } from 'rxjs'
import { ActivatedRoute } from '#angular/router';
import { MembersService } from 'src/app/services/members.service';
#Component({
selector: 'app-member-messages',
templateUrl: './member-messages.component.html',
styleUrls: ['./member-messages.component.css']
})
export class MemberMessagesComponent implements OnInit {
#Input() username: string;
#Input() messages: Message[];
user: User;
member: any;
currentUser$: Observable<User | null>;
messageContent: string;
constructor(
private messageService: MessageService,
private accountService: AccountService,
private route: ActivatedRoute,
private memberService: MembersService
) {
this.accountService.currentUser$.pipe(take(1)).subscribe(x => {
this.currentUser$ = this.accountService.currentUser$;
this.user = x as User;
});
}
ngOnInit() {
const username = this.route.snapshot.paramMap.get('username') as string;
this.memberService.getMember(username).subscribe(member => {
this.member = member;
});
}
sendMessage(form: NgForm) {
this.messageService.sendMessage(this.username, this.messageContent, this.user)
.subscribe((message) => {
this.messages.push(message as Message);
form.reset();
})
}
}
member-messages.html:
<div class="card">
<div class="card-body">
<ng-container *ngIf="messages && messages.length; else noMessages">
<ul class="chat">
<li *ngFor="let message of messages.slice().reverse()">
<span class="chat-img float-right">
<img class="rounded-circle" *ngIf="message.senderUsername && member.username == message.recipientUsername" src="{{user.profile_img || './assets/user.jpg'}}"> <span *ngIf="message.senderUsername && member.username == message.recipientUsername" style="color:red"> {{message.senderUsername}}</span> <img class="rounded-circle" *ngIf="message.recipientUsername && member.username != message.recipientUsername " src="{{member.profile_img || './assets/user.jpg'}}"><span *ngIf="message.recipientUsername && member.username != message.recipientUsername" style="color:green"> {{member.username}}</span>
</span>
<div class="chat-body" >
<p >{{message.content}}</p>
</div>
</li>
</ul>
</ng-container>
<ng-template #noMessages>No messages Yet... say hi bu using the message box bellow</ng-template>
</div>
<div class="card-footer">
<form #messageForm="ngForm" (ngSubmit)="sendMessage(messageForm)" autocomplete="off">
<div class="input-group">
<input
name="messageContent"
required
[(ngModel)]="messageContent"
type="text"
class="form-control input-sm"
placeholder="Send a private message">
<div class="input-group-append">
<button [disabled]="!messageForm.valid" class="btn btn-primary" style="border-radius:0px 5px 5px 0px"type="submit"> Send </button>
</div>
</div>
</form>
</div>
</div>
I think the problem is that you are trying to query for the data field but this field does not exist in your data model.
Solution is to ask data model for messages which contain senderUsername and recipientUsername in the database.
usersRoute
.route("/messages/thread/:username/:senderUsername")
.get(async (req, res) => {
const query = {
senderUsername: req.params.senderUsername,
recipientUsername: req.params.username,
};
const messages = await Messages.find(query).exec();
res.json(messages);
});
Ok, so I managed to find a work around, created another query only this time the senderUser value will be the recipient username and recipientUsername value as the senderUsername :
const query2 = {
senderUsername: req.params.username,
recipientUsername: req.params.senderUsername,
};
Find with both quires while using $or:[query,query2].
the following example worked:
usersRoute
.route("/messages/thread/:username/:senderUsername")
.get(async (req, res) => {
const query = {
senderUsername: req.params.senderUsername,
recipientUsername: req.params.username,
};
const query2 = {
senderUsername: req.params.username,
recipientUsername: req.params.senderUsername,
};
const messages = await Messages.find({$or:[query,query2]}).exec();
console.log(messages);
res.json(messages);
});
Could there be a better way to do it? I would really like to understand this better.
Thank you #Paweł Antyporowicz for the help :)
Error Message on console of post-create.component.html
ERROR TypeError: Cannot read property 'title' of undefined at PostCreateComponent_Template (template.html:13)
I think the problem is here at console.log(form.value.title, form.value.content);
post-create.component.html
<mat-card>
<form (submit)="onAddPost(postform)" #postform="ngForm">
<mat-form-field>
<input
matInput
type="text"
name="title"
[ngModel]="post.title"
required
#title="ngModel"
placeholder="Enter Post Title"
/>
<mat-error *ngIf="title.invalid">Please enter a post title.</mat-error>
</mat-form-field>
<mat-form-field>
<textarea
matInput
rows="6"
name="content"
[ngModel]="post.content"
required
#content="ngModel"
placeholder="Enter Post Content"
></textarea>
<mat-error *ngIf="content.invalid">Please enter a post title.</mat-error>
</mat-form-field>
<button mat-raised-button color="primary" type="submit">Add Post</button>
</form>
</mat-card>
post-create.component.ts (the ts file for the above html file ) please check and help me with the error message thanks in advance!!!
import { Component, OnInit, EventEmitter, Output } from "#angular/core";
import { NgForm } from "#angular/forms";
import { ActivatedRoute, ParamMap } from "#angular/router";
import { Posts } from "../post.model";
import { PostService } from "../post.service";
#Component({
selector: "app-post-create",
templateUrl: "./post-create.component.html",
styleUrls: ["./post-create.component.css"],
})
export class PostCreateComponent implements OnInit {
constructor(public postservice: PostService, public route: ActivatedRoute) {}
private postId: string;
private mode = "create";
post: Posts;
ngOnInit() {
this.route.paramMap.subscribe((paramMap: ParamMap) => {
if (paramMap.has("postId")) {
console.log(paramMap.get("postId"));
this.mode = "edit";
this.postId = paramMap.get("postId");
this.post = this.postservice.getPosts(this.postId);
console.log(this.post);
} else {
this.mode = "create";
this.postId = null;
}
});
}
onAddPost(form: NgForm) {
if (form.invalid) {
return;
}
if (this.mode === "create") {
console.log(form.value.title, form.value.content);
this.postservice.addPosts(form.value.title, form.value.content);
} else {
this.postservice.updatePost(
this.postId,
form.value.title,
form.value.content
);
}
// this.postservice.addPosts(form.value.title, form.value.content);
form.resetForm();
}
}
When you use ngModel with an object property like you did here [ngModel]="post.title" you have to initialize the object with an empty object on its declaration or in the class constructor, or in the ngOnInit method.
So, something like this post: Posts = { title: null, content: null }; will probably solve the issue.
I'm building a blog application based on MEAN stack, using Angular in front-end, node in back-end and mongoDB for server. When I'm trying to access a particular blog by it's blogId, the browser is not showing anything. Although I'm getting the right data fetched from backend with a 304 status and the right blogId is also passing by the route. The console is also logging the right object. Below is my blog-view.component.ts file
import { ActivatedRoute, Router } from '#angular/router';
import { ToastrManager } from 'ng6-toastr-notifications';
import { BlogService } from '../blog.service';
import { BlogHttpService } from '../blog-http.service';
import { Location } from '#angular/common';
#Component({
selector: 'app-blog-view',
templateUrl: './blog-view.component.html',
styleUrls: ['./blog-view.component.css'],
providers: [Location]
})
export class BlogViewComponent implements OnInit, OnDestroy {
public currentBlog;
constructor(private _route: ActivatedRoute, private router: Router, public blogHttpService:BlogHttpService, public toastr: ToastrManager, private location: Location) {
console.log("view-blog constructor called")
}
ngOnInit() {
console.log("view-blog ngOnInIt called");
let myBlogId = this._route.snapshot.paramMap.get('blogId');
console.log(myBlogId);
this.currentBlog = this.blogHttpService.getSingleBlogInformation(myBlogId).subscribe(
data =>{
console.log(data);
this.currentBlog = data["data"];
},
error =>{
console.log("some error occured");
console.log(error.errorMessage);
})
}
public deleteThisBlog(): any {
this.blogHttpService.deleteBlog(this.currentBlog.blogId).subscribe(
data =>{
console.log(data);
this.toastr.successToastr('This blog is successfully deleted.', 'Success!');
setTimeout(() =>{
this.router.navigate(['/home']);
}, 1000)
},
error =>{
console.log(error);
console.log(error.errorMessage);
this.toastr.errorToastr('Some Error Occured.', 'Oops!');
}
)
}
public goBackToPreviousPage(): any {
this.location.back();
}
ngOnDestroy(){
console.log("view-blog component destroyed");
}
}
blog-view.component.html
<div class="row" *ngIf="currentBlog" style="text-align: center;">
<div class="col-md-12">
<h2>{{currentBlog.title}}</h2>
<p>posted by {{currentBlog.author}} on {{currentBlog.created | date:'medium'}}</p>
<p *ngIf="currentBlog.tags!=undefined && currentBlog.tags.length>0">tags : <span *ngFor="let tag of currentBlog.tags;let first=first;let last=last">{{tag}}{{last ? '' : ', '}}</span></p>
<hr>
<div [innerHtml]="currentBlog.bodyHtml"></div>
<hr>
<h5>category - {{currentBlog.category}}</h5>
</div>
<hr>
<div class="row" *ngIf="currentBlog">
<div class="col-md-4">
<a class="btn btn-primary" [routerLink]="['/edit',currentBlog.blogId]">Edit</a>
</div>
<div class="col-md-4">
<a class="btn btn-danger" (click)="deleteThisBlog()">Delete</a>
</div>
<div class="col-md-4">
<a class="btn btn-warning" (click)="goBackToPreviousPage()">Go Back</a>
</div>
</div>
</div>
</div>
blog-http.service.ts
import { HttpClient, HttpErrorResponse } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';
#Injectable()
export class BlogHttpService {
public allBlogs;
public currentBlog;
public baseUrl = 'http://localhost:3000/api/v1/blogs';
constructor(private _http:HttpClient) {
console.log('blog http service constructor called');
}
private handleError(err:HttpErrorResponse){
console.log("handle error http calls");
console.log(err.message);
return Observable.throw(err.message)
}
public getAllBlogs(): any {
let myResponse = this._http.get(this.baseUrl + '/all');
console.log(myResponse);
return myResponse;
}
public getSingleBlogInformation(currentBlogId): any {
let myResponse = this._http.get(this.baseUrl + '/view/' + currentBlogId);
return myResponse;
}
public createBlog(blogData): any {
let myResponse = this._http.post(this.baseUrl + '/create', blogData);
return myResponse;
}
public deleteBlog(blogId): any {
let data = {}
let myResponse = this._http.post(this.baseUrl + '/' + blogId + '/delete', blogId);
return myResponse;
}
public editBlog(blogId, blogData): any {
let myResponse = this._http.put(this.baseUrl + '/' + blogId + '/edit' , blogData);
return myResponse;
}
}
my nodejs routes with controller for blog-view
app.get(baseUrl+'/view/:blogId', (req, res) => {
BlogModel.findOne({ 'blogId': req.params.blogId }, (err, result) => {
if (err) {
console.log(err)
res.send(err)
} else if (result == undefined || result == null || result == '') {
console.log('No Blog Found')
res.send("No Blog Found")
} else {
res.send(result)
}
})
});
Below is a sample document object from which the frontend should render
{
"_id": "5e0e8ac6dcfc4e2008390cdf",
"blogId": "XAY2Qlhb",
"__v": 0,
"lastModified": "2020-01-03T00:28:54.638Z",
"created": "2020-01-03T00:28:54.638Z",
"tags": [
"english movies, action movies"
],
"author": "Decardo",
"category": "Hollywood custom",
"isPublished": true,
"views": 8,
"bodyHtml": "<h1>Heading of the body</h1>\n<p>This is the first blog data getting uploaded n blog project</p>",
"description": "long description>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>",
"title": "Blog Title 1 custom"
}
This line of code will first store a Subscription in this.currentBlog:
this.currentBlog = this.blogHttpService.getSingleBlogInformation(myBlogId).subscribe(...)
Then the subscription will be overwritten by this.currentBlog = data["data"];
this.currentBlog = is actually not needed there.
Not sure if that is the problem. At least it is not proper :)
fetching details from API and trying to list the same getting error while printing the list of users was able print with same code.
following is my home.component.ts
constructor(private formBuilder: FormBuilder, private data: DataService) { }
ngOnInit() {
this.data.getUsers().subscribe(data => {
this.users = data
console.log(this.users);
}
);
}
following is my data services code
getUsers() {
return this.http.get('https://reqres.in/api/users');
}
following is the html loop I am trying
<ul *ngIf="users">
<li *ngFor="let user of users.data">
<img [src]="user.avatar">
<p>{{ user.first_name }} {{ user.last_name }}</p>
</li>
</ul>
Re-Check this from your code Working Stackblitz
component.ts
import { Component, OnInit } from '#angular/core';
import { DataService } from './data.service';
#Component({
selector: 'my-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
users;
constructor(private data: DataService){}
ngOnInit() {
this.data.getUsers().subscribe(data => {
this.users = data ;
})
}
}
service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable()
export class DataService {
constructor(private http: HttpClient) { }
getUsers() {
return this.http.get('https://reqres.in/api/users');
}
}
component.html
<ul *ngIf="users">
<li *ngFor="let user of users.data">
<img [src]="user.avatar">
<p>{{ user.first_name }} {{ user.last_name }}</p>
</li>
</ul>
Worked... I cleared cache of npm and it worked ..
I am currently learning node.js and creating test application using angular so in that i need to retrieve data stored in Mongodb below i have written query to get mongodb data using node.js but unable to get data so what is the exact procedure for changes need to be done in query.
In Html(component in angular):
<div class="col-md-12">
<div class="container">
<table class="table mar-top-20">
<thead class="thead-dark">
<tr>
<th>Date</th>
<th>Client Name</th>
<th>Client Email</th>
<th>Client Password</th>
<th>Action/Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{userDetails.added_on}}</td>
<td>{{userDetails.username}}</td>
<td>{{userDetails.uemail}}</td>
<td>{{userDetails.upassword}}</td>
<td>Show Detail</td>
</tr>
</tbody>
</table>
</div>
</div>
In TS file(component in angular):
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormGroup , Validators } from '#angular/forms';
import { DataService } from '../../../services/data.service';
import { AccountService } from '../../../services/account.service';
import { Router } from '#angular/router';
// import { Client } from '../../../client';
#Component({
selector: 'app-manage-users',
templateUrl: './manage-users.component.html',
styleUrls: ['./manage-users.component.css'],
})
export class ManageUsersComponent implements OnInit {
userDetails: any;
rForm: FormGroup;
post:any;
username: String = '';
uemail: String = '';
upassword: String = '';
constructor(private router: Router,private fb:FormBuilder,private dataService: DataService, private accountService: AccountService) {
this.rForm = fb.group({
'username':['', Validators.required],
'uemail':['', Validators.required],
'upassword': [ '', Validators.required ]
});
}
ngOnInit() {
//Getting user using userId
this.accountService.getUser({ userId: localStorage.getItem('userId') }).subscribe(
response => {
console.log(response);
this.userDetails = JSON.parse(response);
},
err => {
console.error('User Not found');
})
}
}
accountService.ts:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { DataService } from './data.service';
#Injectable()
export class AccountService {
public apiPath: string;//Api URL where we need to send our data & perform related operations
constructor(ds: DataService, private http: HttpClient) {
this.apiPath = ds.apiPath;
}
getUser(user) {//Getting User with userId
return this.http.post(this.apiPath + 'user/getUser', user, { responseType: 'text' });
}
}
UserController.js:
userRouter.post('/getUser', (req, res) => {
var user = {
_id: req.body.userId,
};
Collections.user.findOne(user, function (err, result) {
if (err) return res.status(500).send("There was a problem finding the user");
if (result) {
res.status(200).send(result);
} else {
res.status(500).send("User Not Found with Details: " + JSON.stringify(user));
}
});
});
My database name is testdb and collection name is users