Angular2 SPA (REST API) basic get (CRUD) - rest

Good Morning,
I have my back-end working beautifully but just can’t finish off the front!
I'm confident in my ability to config the back however when I load my desired page I just can’t display my data.
Would someone please advise or direct to a tutorial?
This is what I'm currently using to assist: Angular-2-crud
Thanks GWS
cashmovement-list.component.ts
import { Component, OnInit, ViewChild, Input, Output, trigger, state, style, animate, transition } from '#angular/core';
import { ModalDirective } from 'ng2-bootstrap';
import { DataService } from '../shared/services/data.service';
import { DateFormatPipe } from '../shared/pipes/date-format.pipe';
import { ItemsService } from '../shared/utils/items.service';
import { NotificationService } from '../shared/utils/notification.service';
import { ConfigService } from '../shared/utils/config.service';
import { ICashMovement, Pagination, PaginatedResult } from '../shared/interfaces';
#Component({
moduleId: module.id,
selector: 'cashmovements',
templateUrl: 'cashmovement-list.component.html'
})
export class CashMovementListComponent implements OnInit {
public cashmovements: ICashMovement[];
constructor(private dataService: DataService,
private itemsService: ItemsService,
private notificationService: NotificationService) { }
ngOnInit() {
this.dataService.getCashMovements()
.subscribe((cashmovements: ICashMovement[]) => {
this.cashmovements = cashmovements;
},
error => {
this.notificationService.printErrorMessage('Failed to load users. ' + error);
});
}
}
cashmovement-list.component.html
<button class="btn btn-primary" type="button" *ngIf="cashmovements">
<i class="fa fa-calendar" aria-hidden="true"></i> CashMovements
<span class="badge">{{totalItems}}</span>
</button>
<hr/>
<div [#flyInOut]="'in'">
<table class="table table-hover">
<thead>
<tr>
<th><i class="fa fa-text-width fa-2x" aria-hidden="true"></i>Cash Movement ID</th>
<th><i class="fa fa-user fa-2x" aria-hidden="true"></i>PortfolioCode</th>
<th><i class="fa fa-paragraph fa-2x" aria-hidden="true"></i>CCY Out</th>
<th><i class="fa fa-map-marker fa-2x" aria-hidden="true"></i>Account Out</th>
<th><i class="fa fa-calendar-o fa-2x" aria-hidden="true"></i>Date</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let cashmovement of cashmovements">
<td> {{cashmovement.CashMovementId}}</td>
<td>{{cashmovement.PortfolioCode}}</td>
<td>{{cashmovement.Ccyo}}</td>
<td>{{cashmovement.AccountO}}</td>
<td>{{cashmovement.Date | dateFormat | date:'medium'}}</td>
</tr>
</tbody>
</table>
</div>
interfaces.ts
export interface ICashMovement {
CashMovementId: number;
PortfolioCode: string;
Date: Date;
Ccyo: string;
AccountO: string;
ValueO: number;
Ccyi: string;
AccountI: string;
ValueI: number;
status: string;
comment: string;
LastUpdate: number;
}
app.module.ts
import './rxjs-operators';
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
import { PaginationModule } from 'ng2-bootstrap/ng2-bootstrap';
import { DatepickerModule } from 'ng2-bootstrap/ng2-bootstrap';
import { Ng2BootstrapModule } from 'ng2-bootstrap/ng2-bootstrap';
import { ModalModule } from 'ng2-bootstrap/ng2-bootstrap';
import { ProgressbarModule } from 'ng2-bootstrap/ng2-bootstrap';
import { SlimLoadingBarService, SlimLoadingBarComponent } from 'ng2-slim- loading-bar';
import { TimepickerModule } from 'ng2-bootstrap/ng2-bootstrap';
import { AppComponent } from './app.component';
import { DateFormatPipe } from './shared/pipes/date-format.pipe';
import { HighlightDirective } from './shared/directives/highlight.directive';
import { HomeComponent } from './home/home.component';
import { MobileHideDirective } from './shared/directives/mobile-hide.directive';
import { CashMovementListComponent } from './cashmovements/cashmovement-list.component';
import { routing } from './app.routes';
import { DataService } from './shared/services/data.service';
import { ConfigService } from './shared/utils/config.service';
import { ItemsService } from './shared/utils/items.service';
import { MappingService } from './shared/utils/mapping.service';
import { NotificationService } from './shared/utils/notification.service';
#NgModule({
imports: [
BrowserModule,
DatepickerModule,
FormsModule,
HttpModule,
Ng2BootstrapModule,
ModalModule,
ProgressbarModule,
PaginationModule,
routing,
TimepickerModule
],
declarations: [
AppComponent,
DateFormatPipe,
HighlightDirective,
HomeComponent,
MobileHideDirective,
SlimLoadingBarComponent,
CashMovementListComponent
],
providers: [
ConfigService,
DataService,
ItemsService,
MappingService,
NotificationService,
SlimLoadingBarService
],
bootstrap: [AppComponent]
})
export class AppModule { }
data.service.ts
import { Injectable } from '#angular/core';
import { Http, Response, Headers } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import {Observer} from 'rxjs/Observer';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import { ICashMovement, Pagination, PaginatedResult } from '../interfaces';
import { ItemsService } from '../utils/items.service';
import { ConfigService } from '../utils/config.service';
#Injectable()
export class DataService {
_baseUrl: string = '';
constructor(private http: Http,
private itemsService: ItemsService,
private configService: ConfigService) {
this._baseUrl = configService.getApiURI();
}
getCashMovements(): Observable<ICashMovement[]> {
return this.http.get(this._baseUrl + 'cashmovements')
.map((res: Response) => { return res.json(); })
.catch(this.handleError);
}
private handleError(error: any) {
var applicationError = error.headers.get('Application-Error');
var serverError = error.json();
var modelStateErrors: string = '';
if (!serverError.type) {
console.log(serverError);
for (var key in serverError) {
if (serverError[key])
modelStateErrors += serverError[key] + '\n';
}
}
modelStateErrors = modelStateErrors = '' ? null : modelStateErrors;
return Observable.throw(applicationError || modelStateErrors || 'Server error');
}
}

I think the problem might be in your templateUrl. You need to prefix the partial view with ./ regardless of whether you use moduleId. You need to specify templateUrl: "./cashmovement-list.component.html"
However, if you are getting any error in the dve console of your browser you should post it as an uplate to your question.

Related

How to creat a dynamic text

I have a list of titles, and I would like these texts to alternate as I switch to ion-select. How do I do this?
I have no idea how to do this, not even what part of the code to show. I made an attempt here but whenever I use the console the value returned is undefined.
My typescrit code:
import { Titulo } from './../Services/services.service';
import { DataService } from './data.service';
import { Component, OnInit, ViewChild} from '#angular/core';
import {IonSlides} from '#ionic/angular';
import { ActivatedRoute } from '#angular/router';
#Component({
selector: 'app-libertacao',
templateUrl: './libertacao.page.html',
styleUrls: ['./libertacao.page.scss'],
})
export class LibertacaoPage implements OnInit {
#ViewChild(IonSlides) slides: IonSlides;
PAGINA_SELECIONADA: number;
// tslint:disable-next-line: variable-name
index_atual: number;
titulo: Titulo;
constructor(private dataservice: DataService, private activatedRoute: ActivatedRoute ){
}
ngOnInit() {
const id = this.activatedRoute.snapshot.paramMap.get('id');
this.titulo = this.dataservice.getTituloById(parseInt(id, 10));
}
OnChange(event: any)
{
if (event.detail.value === this.PAGINA_SELECIONADA) {
this.slides.slideTo(this.PAGINA_SELECIONADA);
}
else {}
console.log(this.titulo);
}
slideChanged() {
this.slides.getActiveIndex().then((index) => {
this.index_atual = index;
});
}
}

Fix the TS2345: Argument of type 'HTMLElement' is not assignable to parameter of type 'HTMLInputElement'

I'm trying to setup Google Maps Places Autocomplete in an new Ionic app.
here is the problem. On the first search, I got this error in the console:
TypeError: Cannot read property 'place_id' of undefined
and this error in the terminal:
TS2345: Argument of type 'HTMLElement' is not assignable to parameter of type 'HTMLInputElement'
However, on the second search I get the place_id without any error.
Here is my (simplified) .ts file
import { Component, OnInit } from '#angular/core';
import { google } from "google-maps";
import { Platform } from '#ionic/angular';
#Component({...})
export class AddaddressPage implements OnInit {
autocomplete:any;
constructor(public platform: Platform) {}
ngOnInit() {
this.platform.ready().then(() => {
this.autocomplete = new google.maps.places.Autocomplete(document.getElementById('autocomplete'));
this.autocomplete.setFields(['place_id']);
});
}
fillInAddress() {
var place = this.autocomplete.getPlace();
console.log(place);
console.log(place.place_id);
}
}
and the input I use:
<input id="autocomplete" type="text" (change)="fillInAddress()" />
How should I proceed ?
After playing around, here is the trick! ViewChild and Ion-input are needed.
.html
<ion-input #autocomplete type="text"></ion-input>
.ts
import { Component, OnInit, ViewChild } from '#angular/core';
import { google } from "google-maps";
import { Platform } from '#ionic/angular';
#Component(...)
export class AddaddressPage implements OnInit {
googleAutocomplete:any;
#ViewChild('autocomplete') autocompleteInput: ElementRef;
constructor(public platform: Platform) { }
ngOnInit() {
this.platform.ready().then(() => {
this.autocompleteInput.getInputElement().then((el)=>{
this.googleAutocomplete = new google.maps.places.Autocomplete(el);
this.googleAutocomplete.setFields(['place_id']);
this.googleAutocomplete.addListener('place_changed', () => {
var place = this.googleAutocomplete.getPlace();
console.log(place);
console.log(place.place_id);
});
})
});
}
}

Event listener works outside of the grid but doesn't work inside a cell in ag-grid

I have been struggling with making a simple listener work inside of a cell in ag-grid. What's bothering me is that it works perfectly if I place it in the html file.
In app.component.html:
<select class="form-control" (change)="
RefreshRisqueBrutColumn();"
>
<br>
<option>1- Très improbable</option>
<option>2- Peu probable</option>
<option>3- Possible</option>
<option>4- Probable</option>
</select>
In app.component.ts, I have the listener definition:
public RefreshRisqueBrutColumn() {
const params = { force: true };
this.gridApi.refreshCells(params);
console.log('LISTENER WORKS')
}
So in the browser, when I select an option:
I have this in the console:
Now, I have taken exactly the same select code and I have written it inside the custom cell renderer:
{
headerName: "Probabilité",
headerToolName: "Consultez les échelles",
field: "pbt",
editable: true,
cellRenderer: params => {
return `
<hr>
<select class="form-control" (change)="
RefreshRisqueBrutColumn();"
>
<br>
<option>1- Très improbable</option>
<option>2- Peu probable</option>
<option>3- Possible</option>
<option>4- Probable</option>
</select>
<hr>
`;
}
}
So here's the column in the browser:
So when I select an option, the same thing should happen, right?
However, nothing shows-up in the console.
So I am really curious why isn't this working?
And if possible, how can I fix it?
The cellRenderer expects plain string to be rendered for HTML. The string you are providing in your ColDef is actually an Angular template - which should be compiled into plain HTML. (observe (change)="RefreshRisqueBrutColumn())
Create custom CellRendererComponent, provide the template, define change handler within it and all will work fine.
Reference: Angular Cell Render Components
I have fixed this thanks #Paritosh's tip.
To save you some time, here's how I did it:
This is the custom cell renderer definition:
drop-down-cell-renderer.component.ts
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-drop-down-cell-renderer',
templateUrl: './drop-down-cell-renderer.component.html',
styleUrls: ['./drop-down-cell-renderer.component.css']
})
export class DropDownCellRendererComponent implements OnInit {
constructor() { }
ngOnInit() {
}
params: any;
agInit(params: any): void {
this.params = params;
}
public RefreshRisqueBrutColumn() {
console.log('LISTENER WORKS')
}
}
drop-down-cell-renderer.component.html
<select class="form-control" (change)=" RefreshRisqueBrutColumn();">
<br>
<option>1- Très improbable</option>
<option>2- Peu probable</option>
<option>3- Possible</option>
<option>4- Probable</option>
</select>
app.module.ts
import {BrowserModule} from '#angular/platform-browser';
import {NgModule} from '#angular/core';
import {AppComponent} from './app.component';
import {AgGridModule} from 'ag-grid-angular';
import { DropDownCellRendererComponent } from './drop-down-cell-renderer/drop-down-cell-renderer.component';
#NgModule({
declarations: [
AppComponent,
DropDownCellRendererComponent
],
imports: [
BrowserModule,
AgGridModule.withComponents([DropDownCellRendererComponent])
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {
}
app.component.ts
import {Component, OnInit} from '#angular/core';
import {NumberFormatterComponent} from './number-formatter.component';
import {NumericEditorComponent} from './numeric-editor.component';
import {RangeFilterComponent} from './range-filter.component';
import { DropDownCellRendererComponent } from './drop-down-cell-renderer/drop-down-cell-renderer.component';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
columnDefs = [
{
headerName: "Probabilité",
headerToolName: "Consultez les échelles",
field: "pbt",
editable: true,
cellRenderer: 'dropDownCellRendererComponent'
}
];
rowData = [{}];
frameworkComponents = {
dropDownCellRendererComponent: DropDownCellRendererComponent
};
ngOnInit() {
}
}
And here's the result:
Hope this helps someone :)

displaying a message in angular 6

hello I'm learning angular 6 but I don't understand why it doesn't display my message but he appears in the logs of my server.
component:
import { Component } from '#angular/core';
import { ChatService } from '../chat.service';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
message: string;
messages: string[] = [];
constructor(private chatService: ChatService) {
}
sendMessage() {
this.chatService.sendMessage(this.message);
this.message = '';
}
OnInit() {
this.chatService
.getMessages()
.subscribe((message: string) => {
this.messages.push(message);
});
}
}
html:
<div>
<li *ngFor="let message of messages">
{{message}}
</li>
</div>
<input [(ngModel)]="message" (keyup)="$event.keyCode == 13 && sendMessage()" />
<button (click)="sendMessage()">Send</button>
thanks for your help
chat service :
import * a io from 'socket.io-client';
import {Observable} from 'rxjs';
export class ChatService{
private url = 'http://localhost:3000';
private socket;
constructor() {
this.socket = io(this.url);
}
public sendMessage(message){
this.socket.emit('new-message',message);
}
public getMessage = () => {
return Observable.create((observer) => {
this.socket.on('new-message' , (message) => {
observer.next(message);
});
});
}
}

ERROR TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable

I'm working on autocomplete-search with angular 4. This search bar will get books information from Google Books API. It works fine when I input any search terms. But it causes an error if I remove the entire search term or input a space.This is the error I got
This is my SearchComponent.ts
import { Component, OnInit } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
#Component({
selector: 'app-admin-search',
templateUrl: './admin-search.component.html',
styleUrls: ['./admin-search.component.css']
})
export class AdminSearchComponent implements OnInit {
books: any[] = [];
searchTerm$ = new Subject<string>();
constructor (private bookService: BookService,
private http: HttpClient
) {
this.bookService.search(this.searchTerm$)
.subscribe(results => {
this.books = results.items;
});
}
ngOnInit() {
}
This is my SearchComponent.html
<div>
<h4>Book Search</h4>
<input #searchBox id="search-box"
type="text"
placeholder="Search new book"
(keyup)="searchTerm$.next($event.target.value)"/>
<ul *ngIf="books" class="search-result">
<li *ngFor="let book of books">
{{ book.volumeInfo.title }}
</li>
</ul>
</div>
This is my BookService.ts
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Book } from './book';
import { BOOKS } from './mock-books';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/switchMap';
#Injectable()
export class BookService {
private GoogleBookURL: string = "https://www.googleapis.com/books/v1/volumes?q=";
constructor (private http: HttpClient) { }
search(terms: Observable<string>) {
return terms.debounceTime(300)
.distinctUntilChanged()
.switchMap(term => this.searchEntries(term));
}
searchEntries(searchTerm: string) {
if (searchTerm.trim()) {
searchTerm = searchTerm.replace(/\s+/g, '+');
let URL = this.GoogleBookURL + searchTerm;
return this.http.get(URL);
}
}
}
Can someone help me out? Thanks in advance!
Your method searchEntries returns value (Observable<Response>) only if searchTerm.trim() is true (so it must return non-empty string).
There can be situation that searchEntries will return undefined instead of Obervable<Response> if trim() returns '' (empty string which is false). You can't pass undefined returned from searchEntries into .switchMap(term => this.searchEntries(term));.
For that case your code will look like this:
.switchMap(term => undefined) which is not valid construction.