I have two unrelated components 'chatter-page' and 'header'. I need to have some data shared and synchronized between these two components. I have created a service to do the same. It's not working. Help
chatter-page.component ts file
import { Component, OnInit } from '#angular/core';
import { HostListener } from '#angular/core';
import { DatePipe } from '#angular/common';
import { DropdownItem } from '../shared/dropdownItem';
import { ChatterCard } from '../shared/chattercard';
import { ChatterService } from '../services/chatter.service';
import { FilterShareService } from '../services/filter-share.service';
#Component({
selector: 'app-chatter-page',
templateUrl: './chatter-page.component.html',
styleUrls: ['./chatter-page.component.scss'],
providers : [FilterShareService]
})
export class ChatterPageComponent implements OnInit {
batchSize : number = 50;
dateFilterDisplayFlag : boolean = false;
filterFlag : boolean;
loaderFlag : boolean;
competitors : string[] = ['Company1','Company2'];
categories : string[] = ['Category1','Category2','Category3'];
chatterCards : ChatterCard[] = [];
fromDatePicker;toDatePicker;
dateDisplayFilter : string;
sourceFilters : Set<string>;
sentimentFilters : Set<string>;
organizationFilters : Set<string>;
categoryFilters : Set<string>;
serviceCallString : string = "";
scrollId : string = "";
sourceDropdown : DropdownItem[] = [
{ icon: "fab fa-facebook-f", name: "Facebook" },
{ icon: "fab fa-twitter", name: "Twitter"}
];
sentimentDropdown : DropdownItem[] = [
{ icon: "far fa-smile", name: "Positive" },
{ icon: "far fa-frown", name: "Negative" },
{ icon: "far fa-meh", name: "Neutral"}
];
competitorDropdown : DropdownItem[] = [];
categoryDropdown : DropdownItem[] = [];
constructor(private datePipe : DatePipe, private chatterService : ChatterService, private filterShareService : FilterShareService) { }
#HostListener("window:scroll", [])
onScroll(): void {
let windowHeight = "innerHeight" in window ? window.innerHeight : document.documentElement.offsetHeight;
let body = document.body, html = document.documentElement;
let docHeight = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
let windowBottom = windowHeight + window.pageYOffset;
if (windowBottom >= docHeight) {
console.log("Bottom reached");
this.addDisplayCards();
}
}
receiveFilterFlag(){
this.filterFlag = !this.filterFlag;
}
sourceFilterEvent(filter){
let filters = this.sourceFilters;
this.sourceFilters.has(filter.toUpperCase())? filters.delete(filter.toUpperCase()) : filters.add(filter.toUpperCase());
this.filterShareService.changeSourceFilters(filters);
}
sentimentFilterEvent(filter){
let filters = this.sentimentFilters;
this.sentimentFilters.has(filter.toUpperCase())? filters.delete(filter.toUpperCase()) : filters.add(filter.toUpperCase());
this.filterShareService.changeSentimentFilters(filters);
}
orgFilterEvent(filter){
if(!this.organizationFilters.has(filter.toLowerCase())){
let filters = this.organizationFilters;
filters.clear();
filters.add(filter.toLowerCase());
this.filterShareService.changeOrganizationFilters(filters);
}
}
categoryFilterEvent(filter){
let filters = this.categoryFilters;
this.categoryFilters.has(filter.toUpperCase())? filters.delete(filter.toUpperCase()) : filters.add(filter.toUpperCase());
this.filterShareService.changeCategoryFilters(filters);
}
fromDateEvent(){
let from = new Date(this.fromDatePicker);
let fromDate = this.datePipe.transform(from, 'yyyy-MM-dd');
this.filterShareService.changeFromDate(fromDate);
this.calculateDateDisplayFilter();
this.dateFilterDisplayFlag = true;
}
toDateEvent(){
let to = new Date(this.toDatePicker);
let toDate = this.datePipe.transform(to, 'yyyy-MM-dd');
this.filterShareService.changetoDate(toDate);
this.calculateDateDisplayFilter();
this.dateFilterDisplayFlag = true;
}
calculateDateDisplayFilter(){
this.dateDisplayFilter = this.fromDatePicker + " to " + this.toDatePicker;
}
defaultDateFilter(){
this.dateSetter(180);
}
yesterdayDateFilter(){
this.dateSetter(1);
this.dateFilterDisplayFlag = true;
}
weekDateFilter(){
this.dateSetter(7);
this.dateFilterDisplayFlag = true;
}
monthDateFilter(){
this.dateSetter(30);
this.dateFilterDisplayFlag = true;
}
dateSetter(num){
let from = new Date();
from.setDate(from.getDate()-num);
let fromDate = this.datePipe.transform(from, 'yyyy-MM-dd');
let toDate = this.datePipe.transform(new Date(), 'yyyy-MM-dd');
this.filterShareService.changeFromDate(fromDate);
this.filterShareService.changetoDate(toDate);
this.calculateDateDisplayFilter();
}
populateDropDowns(){
this.competitors.forEach((competitor) => {
this.competitorDropdown.push({ icon: "", name: competitor});
});
this.categories.forEach((category) => {
this.categoryDropdown.push({ icon: "", name: category});
});
}
ngOnInit() {
this.populateDropDowns();
this.filterShareService.currSourceFilters.subscribe((filters) => this.sourceFilters = filters);
this.filterShareService.currSentimentFilters.subscribe((filters) => this.sentimentFilters = filters);
this.filterShareService.currOrganizationFilters.subscribe((filters) => this.organizationFilters = filters);
this.filterShareService.currCategoryFilters.subscribe((filters) => this.categoryFilters = filters);
if(!(this.fromDatePicker && this.toDatePicker)) this.defaultDateFilter();
this.filterShareService.currFromDate.subscribe((date) => this.fromDatePicker = date);
this.filterShareService.currtoDate.subscribe((date) => this.toDatePicker = date);
this.applyFilters();
}
}
header.component ts file
import { Component, OnInit } from '#angular/core';
import { DatePipe } from '#angular/common';
import { DropdownItem } from '../shared/dropdownItem';
import { FilterShareService } from '../services/filter-share.service';
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss'],
providers: [FilterShareService]
})
export class HeaderComponent implements OnInit {
dateFilterDisplayFlag : boolean = false;
filterFlag : boolean;
competitors : string[] = ['Company1','Company2'];
categories : string[] = ['Category1','Category2','Category3'];
fromDatePicker;toDatePicker;
dateDisplayFilter : string;
sourceFilters : Set<string>;
sentimentFilters : Set<string>;
organizationFilters : Set<string>;
categoryFilters : Set<string>;
sourceDropdown : DropdownItem[] = [
{ icon: "fab fa-facebook-f", name: "Facebook" },
{ icon: "fab fa-twitter", name: "Twitter"}
];
sentimentDropdown : DropdownItem[] = [
{ icon: "far fa-smile", name: "Positive" },
{ icon: "far fa-frown", name: "Negative" },
{ icon: "far fa-meh", name: "Neutral"}
];
competitorDropdown : DropdownItem[] = [];
categoryDropdown : DropdownItem[] = [];
constructor(private datePipe : DatePipe, private filterShareService : FilterShareService) { }
receiveFilterFlag(){
this.filterFlag = !this.filterFlag;
}
sourceFilterEvent(filter){
let filters = this.sourceFilters;
this.sourceFilters.has(filter.toUpperCase())? filters.delete(filter.toUpperCase()) : filters.add(filter.toUpperCase());
this.filterShareService.changeSourceFilters(filters);
}
sentimentFilterEvent(filter){
let filters = this.sentimentFilters;
this.sentimentFilters.has(filter.toUpperCase())? filters.delete(filter.toUpperCase()) : filters.add(filter.toUpperCase());
this.filterShareService.changeSentimentFilters(filters);
}
orgFilterEvent(filter){
if(!this.organizationFilters.has(filter.toLowerCase())){
let filters = this.organizationFilters;
filters.clear();
filters.add(filter.toLowerCase());
this.filterShareService.changeOrganizationFilters(filters);
}
}
categoryFilterEvent(filter){
let filters = this.categoryFilters;
this.categoryFilters.has(filter.toUpperCase())? filters.delete(filter.toUpperCase()) : filters.add(filter.toUpperCase());
this.filterShareService.changeCategoryFilters(filters);
}
fromDateEvent(){
console.log("Inside dash header")
let from = new Date(this.fromDatePicker);
let fromDate = this.datePipe.transform(from, 'yyyy-MM-dd');
this.filterShareService.changeFromDate(fromDate);
this.calculateDateDisplayFilter();
this.dateFilterDisplayFlag = true;
}
toDateEvent(){
let to = new Date(this.toDatePicker);
let toDate = this.datePipe.transform(to, 'yyyy-MM-dd');
this.filterShareService.changetoDate(toDate);
this.calculateDateDisplayFilter();
this.dateFilterDisplayFlag = true;
}
calculateDateDisplayFilter(){
this.dateDisplayFilter = this.fromDatePicker + " to " + this.toDatePicker;
}
defaultDateFilter(){
this.dateSetter(180);
}
yesterdayDateFilter(){
this.dateSetter(1);
this.dateFilterDisplayFlag = true;
}
weekDateFilter(){
this.dateSetter(7);
this.dateFilterDisplayFlag = true;
}
monthDateFilter(){
this.dateSetter(30);
this.dateFilterDisplayFlag = true;
}
dateSetter(num){
let from = new Date();
from.setDate(from.getDate()-num);
let fromDate = this.datePipe.transform(from, 'yyyy-MM-dd');
let toDate = this.datePipe.transform(new Date(), 'yyyy-MM-dd');
this.filterShareService.changeFromDate(fromDate);
this.filterShareService.changetoDate(toDate);
this.calculateDateDisplayFilter();
}
populateDropDowns(){
this.competitors.forEach((competitor) => {
this.competitorDropdown.push({ icon: "", name: competitor});
});
this.categories.forEach((category) => {
this.categoryDropdown.push({ icon: "", name: category});
});
}
ngOnInit() {
this.populateDropDowns();
this.filterShareService.currSourceFilters.subscribe((filters) => this.sourceFilters = filters);
this.filterShareService.currSentimentFilters.subscribe((filters) => this.sentimentFilters = filters);
this.filterShareService.currOrganizationFilters.subscribe((filters) => this.organizationFilters = filters);
this.filterShareService.currCategoryFilters.subscribe((filters) => this.categoryFilters = filters);
if(!(this.fromDatePicker && this.toDatePicker)) this.defaultDateFilter();
this.filterShareService.currFromDate.subscribe((date) => this.fromDatePicker = date);
this.filterShareService.currtoDate.subscribe((date) => this.toDatePicker = date);
}
}
The fromDatePicker and toDatePicker variables, which are supposed to store calues from two date input fields (from date, to date) which are present in both the components. sourceFilters, sentimentFilters, organizationFilters & categoryFilters are sets of strings.
I need to synchronize the fromDatePicker, toDatePicker, sourceFilters, sentimentFilters, organizationFilters & categoryFilters values between both the components always. This is my filter share service
import { Injectable } from '#angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
#Injectable()
export class FilterShareService {
private sourceFilters = new BehaviorSubject<Set<string>>(new Set<string>());
currSourceFilters = this.sourceFilters.asObservable();
private sentimentFilters = new BehaviorSubject<Set<string>>(new Set<string>());
currSentimentFilters = this.sentimentFilters.asObservable();
private organizationFilters = new BehaviorSubject<Set<string>>(new Set<string>(["vanguard"]));
currOrganizationFilters = this.organizationFilters.asObservable();
private categoryFilters = new BehaviorSubject<Set<string>>(new Set<string>());
currCategoryFilters = this.categoryFilters.asObservable();
private fromDate = new BehaviorSubject<string>("");
currFromDate = this.fromDate.asObservable();
private toDate = new BehaviorSubject<string>("");
currtoDate = this.toDate.asObservable();
constructor() { }
changeFromDate(date: string){
this.fromDate.next(date);
console.log("Inside service");
console.log(this.fromDate);
}
changetoDate(date: string){
this.toDate.next(date);
}
changeSourceFilters(sourceFilters: Set<string>){
this.sourceFilters.next(sourceFilters);
}
changeSentimentFilters(sentimentFilters: Set<string>){
this.sentimentFilters.next(sentimentFilters);
}
changeOrganizationFilters(organizationFilters: Set<string>){
this.organizationFilters.next(organizationFilters);
}
changeCategoryFilters(categoryFilters: Set<string>){
this.categoryFilters.next(categoryFilters);
}
}
What am i doing wrong? Any help is appreciated. TIA
Remove the [provider] from both chatter-page and header component.
import { Component, OnInit } from '#angular/core';
import { HostListener } from '#angular/core';
import { DatePipe } from '#angular/common';
import { DropdownItem } from '../shared/dropdownItem';
import { ChatterCard } from '../shared/chattercard';
#Component({
selector: 'app-chatter-page',
templateUrl: './chatter-page.component.html',
styleUrls: ['./chatter-page.component.scss']
})
export class ChatterPageComponent implements OnInit {
}
and
header-component.ts
import { Component, OnInit } from '#angular/core';
import { DatePipe } from '#angular/common';
import { DropdownItem } from '../shared/dropdownItem';
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss'],
})
export class HeaderComponent implements OnInit {
}
having providers: [FilterShareService] means you are initiating the service all the time. So HeaderComponent will have a new separate FilterShareService and ChatterPageComponent will have a separate one. That way they can share .
Move it to your app.module.ts like below.
#NgModule({
imports: [
BrowserModule,
],
declarations: [
HeaderComponent ,
ChatterPageComponent
],
providers: [
FilterShareService,
ChatterService
],
bootstrap: [
AppComponent
]
})
export class AppModule { }
Now the service will be shared across all the modules under your AppModule.
Related
I have clients who have their segments (from A to G).
At HomeComponent, I get all these clients. Then they are displayed on the map in MapComponent.
There is also AsideComponent where I have Inputs in the form of Customer Segments (i.e. from A-G, as there are customers).
At this point I have done so that by clicking on Aside I Emit the table of "Segments" clicked to HomaController (argument checkedSegment) and with it I would like to filter all current clients (currentClientList), that is on currentClientList (it has a field called Segment because it is an array of customers) it should contain dynamically all customers that fall within any of the segments.
HomeController :
import { Component, OnInit } from '#angular/core';
import { User } from '../Models/User';
import { UserService } from '../Services/UserServices';
import { Client } from '../Models/Client';
import { ClientService } from '../Services/ClientService';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
currentUser$: User;
currentClientList : Client[];
currentSegments : string[];
checkedSegment: string[] = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
currentPH : string[];
checkedPH:string[]= [];
constructor(private user: UserService,private client: ClientService) {
}
ngOnInit(): void {
this.setCurrentUser();
this.getCurrentUser();
this.getClients();
}
setCurrentUser(): void{
const user: User = JSON.parse(localStorage.getItem('user'));
this.user.setCurrentUser(user);
}
getCurrentUser(): void {
// this.currentUser$ = JSON.parse(localStorage.getItem('user'));
this.user.currentUser$.subscribe((response) => {
this.currentUser$ = response;
});
}
getClients(): void {
this.client.getClients()
.subscribe((response) => {
this.currentClientList = response;
this.currentPH = this.removeDuplicatePH(this.currentClientList);
this.onMapNotify(this.currentClientList);
});
}
removeDuplicateSegment(cli: Client[]) {
// tslint:disable-next-line: no-shadowed-variable
const clients = cli.map(clients => clients.segment).sort();
return [...new Set(clients)];
}
removeDuplicatePH(cli: Client[]) {
// tslint:disable-next-line: no-shadowed-variable
const clients = cli.map(clients => clients.ph).sort();
return [...new Set(clients)];
}
onMapNotify(clients: Client[]) : void{
this.currentClientList = clients;
this.currentSegments = this.removeDuplicateSegment(clients);
this.currentPH = this.removeDuplicatePH(clients);
}
recieveCheckedSegment(e) {
console.log(e);
if (e.isChecked === true) {
this.checkedSegment.push(e.segment);
} else {
let i = this.checkedSegment.indexOf(e.segment);
if (i != -1) {
this.checkedSegment.splice(i, 1);
}
}
console.log(this.checkedSegment);
this.filterClients();
}
filterClients() {
console.log("wyfiltrowane przez " + this.checkedSegment);
let currSegmentChecked = this.checkedSegment;
const tempClient = this.currentClientList.map(x => x.segment).filter(function(segment){
return segment.indexOf(segment) >= 0 ;
},currSegmentChecked)
console.log(this.currentClientList.map(x => x.segment));
}
}
Home.Component.hmtl
<div class="wrapper">
<app-header></app-header>
<div class="mainapp">
<app-map class="map" [clientList]= "currentClientList" *ngIf="currentUser$" (klienci)="onMapNotify($event)"></app-map>
<app-aside [Segmenty]= "currentSegments" [PH]= "currentPH" class="aside" *ngIf="currentUser$" (checkedPH)= "recieveCheckedPH($event)"
(checkedSegment)= "recieveCheckedSegment($event)"> {{checkedSegment}} {{checkedPH}}
</app-aside>
</div>
</div>
AsideComponent
import { Component, EventEmitter, Input, OnInit, Output } from '#angular/core';
#Component({
selector: 'app-aside',
templateUrl: './aside.component.html',
styleUrls: ['./aside.component.css']
})
export class AsideComponent implements OnInit {
#Input() Segmenty;
#Output() checkedSegment = new EventEmitter<{}>();
#Input() PH;
#Output() checkedPH = new EventEmitter<{}>();
constructor() {
}
ngOnInit(): void {
}
emitCheckedValue(event, segment) {
// console.log(event.srcElement.checked);
this.checkedSegment.emit({
isChecked: event.srcElement.checked,
segment: segment
});
}
emitCheckedPH(event, ph) {
// console.log(event.srcElement.checked);
this.checkedPH.emit({
isChecked: event.srcElement.checked,
ph : ph
});
}
}
aside.component.html
<div class="box">
<div class="segment">
<div *ngFor ="let segment of Segmenty; let i = index" >
<input type="checkbox" checked="true" (change)="emitCheckedValue($event,segment)">
<span>{{segment}}</span>
</div>
</div>
</div>
Please find my existing script,
Directory Structure:
App/
->Classes
->Components
->Services Index.html
Script Sample:
Index.html
<html lang="en">
<head>
</head>
<body>
<app-root></app-root>
</body>
</html>
App/app.module.ts
import { BrowserModule, Title } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { HttpClientModule } from '#angular/common/http';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import { CookieService } from 'ngx-cookie-service';
import { environment } from 'src/environments/environment';
// Datepicker module
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { BsDatepickerModule } from 'ngx-bootstrap/datepicker';
import { OwlModule } from 'ngx-owl-carousel';
import { CarouselModule } from 'ngx-bootstrap/carousel';
import { AppComponent } from './app.component';
import { HeaderComponent } from './components/header/header.component';
import { FooterComponent } from './components/footer/footer.component';
import { HomeComponent } from './components/home/home.component';
import { AppRoutingModule } from './app-routing.module';
#NgModule({
declarations: [
AppComponent,
HeaderComponent,
FooterComponent,
HomeComponent
],
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
AppRoutingModule,
HttpClientModule,
OwlModule,
CarouselModule.forRoot(),
BrowserAnimationsModule,
BsDatepickerModule
],
providers: [CookieService, Title, { provide: 'BASE_API_URL', useValue: environment.baseUrl}],
bootstrap: [AppComponent]
})
export class AppModule {
constructor() {}
}
app.component.html
<div class="page-wrapper">
<app-header></app-header>
<router-outlet></router-outlet>
<app-footer></app-footer>
</div>
Header Component HTML:
<header class="site-header">
<div class="container">
<div class="align-items-center row">
<div class="col-lg-3">
<div class="logo">
<a [routerLink]="['/']">
<img src="assets/images/deluxify-logo.png" alt="Deluxify">
</a>
</div>
</div>
<div class="col-lg-9">
<div class="headertopright">
<nav class="main-navigation">
<ul class="menu">
<li><a [routerLink]="['categories']">Discover</a></li>
<li><a [routerLink]="['how-it-works']">How It Works</a></li>
<li><a [routerLink]="['faq']">FAQ</a></li>
<li><a [routerLink]="['contact']">Contact</a></li>
</ul>
</nav>
<div class="searchbox">
<div class="txtdiv">
<input type="text"
placeholder="Search"
name="search" class="searchfield"
autocomplete="off"
>
</div>
<div class="selectDiv">
<select id="head_category">
<option value="bags">Bags</option>
<option value="jewellery">Jewellery</option>
<option value="sunglasses">Sunglasses</option>
<option value="watches">Watches</option>
</select>
</div>
</div>
<a href="javascript:void(0)" class="togglemenu menu-trigger">
<span></span>
<span></span>
<span></span>
</a>
<a [routerLink]="['/','category', 'bags']" class="togglesearch searchicon"></a>
</div>
</div>
</div>
</div>
</header>
Header Component TS file:
import { Component, OnInit } from '#angular/core';
declare var jQuery:any;
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
constructor() {}
ngOnInit() {
}
}
Search Component ts
import { Component, EventEmitter, Output, Input, OnInit } from '#angular/core';
import { Params, Router, ActivatedRoute } from '#angular/router';
import {switchMap} from 'rxjs/operators';
import { Options, ChangeContext, PointerType, LabelType } from 'ng5-slider';
import { ProductService } from './../../services/product.service';
import { CategoryService } from './../../services/category.service';
import { NgxSpinnerService } from 'ngx-spinner';
declare var jQuery: any;
#Component({
selector: 'app-product',
templateUrl: './product.component.html',
styleUrls: ['./product.component.css']
})
export class ProductComponent implements OnInit {
filterOptions:any = {};
products: any;
notEmptyPost = true;
notscrolly = true;
isCatLoaded = false;
dataLength: any;
catname: any;
error: {};
config: any;
brandArr: any[] = [];
idealforArr: any[] = [];
shapeArr: any[] = [];
framecolorArr: any[] = [];
typeArr: any[] = [];
colorArr: any[] = [];
meterialArr: any[] = [];
sizeArr: any[] = [];
styleArr: any[] = [];
stoneArr: any[] = [];
weightArr: any[] = [];
occasionArr: any[] = [];
framesizeArr: any[] = [];
lenscolorArr: any[] = [];
frame_typeArr: any[] = [];
frame_materialArr: any[] = [];
strap_materialArr: any[] = [];
strap_colorArr: any[] = [];
dial_colorArr: any[] = [];
dial_ShapeArr: any[] = [];
constructor(
private ProductService: ProductService,
private CategoryService: CategoryService,
private route: ActivatedRoute,
private router: Router,
private spinner: NgxSpinnerService) {
this.config = {
currentPage: 1,
itemsPerPage: 16,
totalItems: 0,
filterPerms: {}
};
this.config.filterPerms.slug = this.route.snapshot.paramMap.get('slug')? this.route.snapshot.paramMap.get('slug') : 'bags';
}
priceSliderMinValue: number = 100;
priceSliderMaxValue: number = 9999;
options: Options = {
floor: this.priceSliderMinValue,
ceil: this.priceSliderMaxValue,
step: 10,
// showTicks: true,
translate: (value: number, label: LabelType): string => {
switch (label) {
case LabelType.Low:
return '$' + value;
case LabelType.High:
return '$' + value;
default:
return '$' + value;
}
}
};
onPriceChangeEnd(changeContext: ChangeContext): void {
this.config.filterPerms.min_price = changeContext.value;
this.config.filterPerms.max_price = changeContext.highValue;
this.resetLoadMore();
this.getProducts();
}
value: number = 1;
highValue: number = 10;
optionsdistance: Options = {
floor: 1,
ceil: 10,
step: 1,
showTicks: true,
translate: (value: number, label: LabelType): string => {
switch (label) {
case LabelType.Low:
return value + 'KM';
case LabelType.High:
return value + 'KM';
default:
return value + 'KM';
}
}
};
brandChecked(event){
let sCriteriaStr = event.target.name;
let sCriteria = sCriteriaStr.replace("chk_", "");
if (sCriteria === 'brand') {
this.config.filterPerms.brand = this.findSearchableString(event, this.brandArr, sCriteria);
}
if (sCriteria === 'idealfor') {
this.config.filterPerms.idealfor = this.findSearchableString(event, this.idealforArr, sCriteria);
}
if (sCriteria === 'shape') {
this.config.filterPerms.shape = this.findSearchableString(event, this.shapeArr, sCriteria);
}
if (sCriteria === 'framecolor') {
this.config.filterPerms.framecolor = this.findSearchableString(event, this.framecolorArr, sCriteria);
}
if (sCriteria === 'type') {
this.config.filterPerms.type = this.findSearchableString(event, this.typeArr, sCriteria);
}
if (sCriteria === 'color') {
this.config.filterPerms.color = this.findSearchableString(event, this.colorArr, sCriteria);
}
if (sCriteria === 'meterial') {
this.config.filterPerms.meterial = this.findSearchableString(event, this.meterialArr, sCriteria);
}
if (sCriteria === 'size') {
this.config.filterPerms.size = this.findSearchableString(event, this.sizeArr, sCriteria);
}
if (sCriteria === 'style') {
this.config.filterPerms.style = this.findSearchableString(event, this.styleArr, sCriteria);
}
if (sCriteria === 'stone') {
this.config.filterPerms.stone = this.findSearchableString(event, this.stoneArr, sCriteria);
}
if (sCriteria === 'weight') {
this.config.filterPerms.weight = this.findSearchableString(event, this.weightArr, sCriteria);
}
if (sCriteria === 'occasion') {
this.config.filterPerms.occasion = this.findSearchableString(event, this.occasionArr, sCriteria);
}
if (sCriteria === 'framesize') {
this.config.filterPerms.framesize = this.findSearchableString(event, this.framesizeArr, sCriteria);
}
if (sCriteria === 'lenscolor') {
this.config.filterPerms.lenscolor = this.findSearchableString(event, this.lenscolorArr, sCriteria);
}
if (sCriteria === 'frame_type') {
this.config.filterPerms.frame_type = this.findSearchableString(event, this.frame_typeArr, sCriteria);
}
if (sCriteria === 'frame_material') {
this.config.filterPerms.frame_material = this.findSearchableString(event, this.frame_materialArr, sCriteria);
}
if (sCriteria === 'strap_material') {
this.config.filterPerms.strap_material = this.findSearchableString(event, this.strap_materialArr, sCriteria);
}
if (sCriteria === 'strap_color') {
this.config.filterPerms.strap_color = this.findSearchableString(event, this.strap_colorArr, sCriteria);
}
if (sCriteria === 'dial_color') {
this.config.filterPerms.dial_color = this.findSearchableString(event, this.dial_colorArr, sCriteria);
}
if (sCriteria === 'dial_Shape') {
this.config.filterPerms.dial_Shape = this.findSearchableString(event, this.dial_ShapeArr, sCriteria);
}
this.resetLoadMore();
this.getProducts();
}
findSearchableString(event, checkedArr, filterOptionKey){
let tVal = event.target.value;
if(event.target.checked) {
checkedArr.push(tVal);
}
else {
for(var i=0 ; i < this.filterOptions[filterOptionKey].length; i++) {
if(checkedArr[i] === tVal) {
checkedArr.splice(i,1);
}
}
}
return checkedArr.join('~');
}
onDateChange(event) {
if (event) {
var dtEvent = new Date(event);
let date = JSON.stringify(dtEvent)
date = date.slice(1,11);
if (date) {
this.config.filterPerms.availability_date = date;
this.resetLoadMore();
this.getProducts();
}
}
}
// pageChanged(event) {
// this.config.currentPage = event;
// }
getFilterOptions() {
return new Promise((resolve, reject) => {
this.route.params.pipe(
switchMap((params: Params) => this.CategoryService.getCategoryBySlug(this.config.filterPerms.slug)
)
).subscribe((res: any) => {
this.config.filterPerms.category = res.records;
this.isCatLoaded=true;
if (this.config.filterPerms.category[0].id) {
this.route.params.pipe(
switchMap((params: Params) => this.ProductService.getFilterOptions(this.config)
)
).subscribe((res: any) => {
this.filterOptions = res;
this.priceSliderMinValue = this.filterOptions.min;
this.priceSliderMaxValue = this.filterOptions.max;
resolve();
});
}
});
});
}
getProducts() {
this.spinner.show();
this.route.params.pipe(
switchMap((params: Params) => this.ProductService.getFilterProducts(this.config)
)
).subscribe((res: any) => {
if (!res.success) {
console.log("Error found in fetching data!");
} else {
this.spinner.hide();
this.products = res.records;
}
});
}
sortBy(sort_by) {
this.config.filterPerms.sort_by = sort_by.target.value;
if (sort_by) {
this.resetLoadMore();
this.getProducts();
}
}
resetLoadMore() {
this.config.filterPerms.lastPostId = '';
this.config.filterPerms.curNumRec = '';
}
onScroll() {
if (this.notscrolly && this.notEmptyPost) {
this.spinner.show();
this.notscrolly = false;
this.loadNextPost();
}
}
// load th next 6 posts
loadNextPost() {
if (this.isCatLoaded && this.products) {
const lastPost = this.products[0];
//this.config.filterPerms.lastPostId = lastPost.id;
this.config.filterPerms.curNumRec = this.products.length;
this.route.params.pipe(
switchMap((params: Params) => this.ProductService.getFilterProducts(this.config)
)).subscribe((res: any) => {
this.spinner.hide();
if (res.records.length === 0 ) {
this.notEmptyPost = false;
}
this.products = this.products.concat(res.records);
this.notscrolly = true;
});
}
}
ngOnInit() {
this.getFilterOptions().then(res => this.getProducts());
}
}
I am facing issue in search from header all filter script performs perfectly which are write in search component but search by keyword defined in header component then how to perform search from header.
Both component are parent there is no relation between child and parent concept you can view the component relation in app.component.html file.
Search page load on demand and header footer page load while start the project.
So please help anyone how to do it with better way.
What you have done so far is completely fine. I have created a working example of the code I have below: https://stackblitz.com/edit/angular-khwjt3?file=src%2Fapp%2Fapp.component.ts
First, need to add a new service. This service will relay all search input events out to anything in your app that listens to it.
#Injectable({
providedIn: 'root'
})
export class GlobalSearchService {
public searchTerm: BehaviorSubject<string> = new BehaviorSubject<string>(null);
}
HeaderComponent.html Add a new input event to your search box
<input (input)="onInput($event)" type="text" placeholder="Search" name="search" class="searchfield" autocomplete="off" >
HeaderComponent.ts Add an event listener for it
public onInput(event: any){
// this pushes the input value into the service's Observable.
this.globalSearchService.searchTerm.next(event.target.value);
}
Product Component.ts Now we just have to subscribe to our new Observable.
ngOnInit(){
// this listens to the input value from the service and does something on change.
this.globalSearchService.searchTerm.subscribe((newValue: string) => {
// this is where you would apply your existing filtering.
this.searchTerm = newValue;
});
}
I'm trying to do an action after creating an event.
Create a control form that has been selected in form1 several p, and update a PSelected table.
I have two files, A.html and A.ts
A.html:
<mat-select placeholder="form1" [formControl]="product" (ngModelChange)="getP($event)" multiple> <mat-option *ngFor="let p of allProduct" [value]="p.pro_nom">{{p.pro_nom}}</mat-option>
</mat-select>
<mat-form-field *ngFor="let valeurControls of valeursControls">
<input matInput maxLength="255" type="text [placeholder]="valeurControls.valeur.n [formControl]="valeurControls.formControl">
</mat-form-field>
A.ts:
import { ChangeDetectorRef, Component, OnInit, ViewEncapsulation, Output, EventEmitter } from '#angular/core';
import { FormBuilder, FormControl, FormGroup, Validators } from '#angular/forms';
import { filter, takeUntil } from 'rxjs/operators';
import { Product, Candy } from 'src/app/models';
import { Service } from 'src/app/services';
import { Listener } from 'selenium-webdriver';
#Component({
selector: 'ei',
templateUrl: './A.component.html',
styleUrls: ['./A.component.less'],
encapsulation: ViewEncapsulation.None
})
export class AComponent extends FormFieldsContainer implements OnInit {
#Output('change') inputChange = new EventEmitter();
//var
allProduct: Product[];
Candy: Candy;
// Form
actionFormGroup: FormGroup;
product: FormControl;
event: Listener[]
// P
valeursControls: { valeur: candy, formControl: FormControl }[] = [];
public pSelected: Array<any>;
// Constructor
constructor(private fb: FormBuilder) {
super();
this.Candy = this.Candy ? this.Candy : { name: null, type: null };
this.pSelected = [];
this.buildForm();
}
ngOnInit() {
this.Service.getProduct()
.pipe(takeUntil(this.unsubscribe))
.subscribe(p => {
this.allProduct = p;
});
}
getP(event?: Event[]) {
if (typeof event == 'undefined') {
this.pSelected = [];
} else {
this.pSelected = event;
}
console.log(this.pSelected)
return this.pSelected;
}
getFormGroup(): FormGroup {
return this.actionFormGroup;
}
onSubmitSuccess<Boolean>(result: Boolean) {
}
private buildForm() {
this.submitted = false;
this.p= this.fb.control('', Validators.required);
this.actionFormGroup = this.fb.group({
product: this.product
});
// my array does not update, it remains empty
this.pSelected .forEach(p => {
const VarFormControl = this.fb.control(null);
this.valeursControls.push({
valeur: { name: p, type: this.Candy.type },
formControl: VarFormControl
});
this.actionFormGroup.addControl(p, VarFormControl );
});
}
Actions() {
this.submitted = true;
}
}
in the function getP(), my table is updating, but when I use it in buildForm() it is empty yet it should have the same value
you are calling this.buildForm(); from the component constructor.
The value of pSelected will be the declared one: public pSelected: Array;
You should rebuild valeursControls any time you select/unselect a value inside the mat-select component.
try:
getP(event?: Event[]) {
this.valeursControls = [];
if (typeof event == 'undefined') {
this.pSelected = [];
} else {
this.pSelected = event;
this.buildValeursControls();
}
}
private buildValeursControls(){
this.pSelected.forEach(p => {
const VarFormControl = this.fb.control(null);
this.valeursControls.push({
valeur: { n: p, r: this.B.r },
formControl: VarFormControl
});
this.actionFormGroup.addControl(p, VarFormControl );
});
}
private buildForm() {
this.submitted = false;
this.p= this.fb.control('', Validators.required);
this.actionFormGroup = this.fb.group({
p: this.p
});
}
I have created a mat-table to display list of Jobs.
Now I want to add a mat-filter to search a job using date or JobId.
However the code that I have written doesn't seem to work.
It does not throw any errors and it doesn't filter data.
HTML Code:
<mat-form-field>
<input
matInput
(keyup)="applyFilter($event.target.value)"
placeholder="Search"
/>
</mat-form-field>
<mat-table [dataSource]="jobExecutionList">
...
Typescript Code:
jobExecutionList: any = [];
applyFilter(filterValue: string) {
this.jobExecutionList.filter = filterValue.trim().toLowerCase();
}
Whole Typescript file :
import { Component, OnInit } from "#angular/core";
import { MatTableDataSource } from "#angular/material";
import { GlobalAppSateService } from "../../services/globalAppSate.service";
import { DataService } from "../../services/data.service";
import { SnakBarComponent } from "../custom-components/snak-bar/snak-
bar.component";
import { DataSource } from "#angular/cdk/collections";
import { Observable, of } from "rxjs";
import {
animate,
state,
style,
transition,
trigger
} from "#angular/animations";
import { RecommendationService } from "../recommendation-service.service";
import { MessageService } from '../../services/message.service';
#Component({
selector: "app-job-execution-screen",
templateUrl: "./job-execution-screen.component.html",
styleUrls: ["./job-execution-screen.component.scss"],
animations: [
trigger("detailExpand", [
state(
"collapsed",
style({ height: "0px", minHeight: "0", visibility: "hidden" })
),
state("expanded", style({ height: "*", visibility: "visible" })),
transition(
"expanded <=> collapsed",
animate("225ms cubic-bezier(0.4, 0.0, 0.2, 1)")
)
])
]
})
export class JobExecutionScreenComponent implements OnInit {
displaySpinner: boolean = false;
jobId: string;
jobExecutionList: any = [];
jobExecStatDisplayedColumns = [
"jobId",
"executionDate",
"previousTimePeriod",
"afterTimePeriod",
"status",
"actions",
"spinner"
];
public selectedElem: any;
projectjobId: any = 1;
jobExecutionStat: any;
executionDate: string = new Date().toISOString().slice(0, 10);
executeJobStop: any;
changeStatus: any;
newStatus: any;
isExpansionDetailRow = (i: number, row: Object) =>
row.hasOwnProperty("detailRow");
expandedElement: any;
constructor(
private dataService: DataService,
public globalAppSateService: GlobalAppSateService,
private snakbar: SnakBarComponent,
private recommendationService: RecommendationService,
private messageService: MessageService
) {}
ngOnInit() {
const project = JSON.parse(this.dataService.getObject("project"));
if (project != null) {
this.globalAppSateService.onMessage(project);
}
// API to get list of Running Jobs
this.recommendationService
.getJobExecutionStatList(this.projectjobId)
.subscribe(data => {
this.jobExecutionList = data;
console.log(this.jobExecutionList);
// this.jobExecutionStat = new ExampleDataSource();
});
}
applyFilter(filterValue: string) {
this.jobExecutionList.filter = filterValue.trim().toLowerCase();
}
stop_exec_job(element) {
if (element.status == "Running" || element.status == "Pending") {
//Api to stop Job Execution
this.recommendationService
.stopJobExecution(element.jobId, "Cancelled")
.subscribe(data => {
this.executeJobStop = data;
//this.changeStatus.push(this.executeJobStop);
// this.newStatus = new ExampleDataSource();
});
this.displaySpinner = false;
element.status = "Cancelled";
this.snakbar.statusBar("Job Execution Stopped", "Sucess");
} else {
this.snakbar.statusBar("Job Failed to start", "Failure");
}
}
// Will need it for mat-progress bar
// stop_exec_job2() {
// this.stop_exec_job(this.selectedElem);
// this.displaySpinner = false;
// }
re_run_job(element) {
if (
element.status == "Cancelled" ||
element.status == "Completed" ||
element.status == "Executed" ||
element.status == "FINISHED"
) {
//Api to Re-Run Job Execution
this.recommendationService
.stopJobExecution(element.jobId, "Running")
.subscribe(data => {
this.executeJobStop = data;
//this.changeStatus.push(this.executeJobStop);
// this.newStatus = new ExampleDataSource();
});
this.displaySpinner = true;
element.status = "Running";
this.snakbar.statusBar("Job Execution Started", "Sucess");
this.messageService.messageReceived$.subscribe(data => {
this.snakbar.statusBar(
'Platform job status - ' + data,
'Info'
);
//this.isLoadingResults = false;
});
} else {
this.snakbar.statusBar("Job Failed to start", "Failure");
}
}
}
export interface Element {
jobId: number;
executionDate: string;
previousTimePeriod: string;
afterTimePeriod: string;
status: string;
}
This is the Whole typescript file.
Based on different comment, you need to do:
dataSource: MatTableDataSource<any>;
And then when you get the data:
this.dataSource = new MatTableDataSource(/** YOUR DATA **/);
In your example:
import { Component, OnInit } from "#angular/core";
import { MatTableDataSource } from "#angular/material";
import { GlobalAppSateService } from "../../services/globalAppSate.service";
import { DataService } from "../../services/data.service";
import { SnakBarComponent } from "../custom-components/snak-bar/snak-
bar.component";
import { DataSource } from "#angular/cdk/collections";
import { Observable, of } from "rxjs";
import {
animate,
state,
style,
transition,
trigger
} from "#angular/animations";
import { RecommendationService } from "../recommendation-service.service";
import { MessageService } from '../../services/message.service';
#Component({
selector: "app-job-execution-screen",
templateUrl: "./job-execution-screen.component.html",
styleUrls: ["./job-execution-screen.component.scss"],
animations: [
trigger("detailExpand", [
state(
"collapsed",
style({ height: "0px", minHeight: "0", visibility: "hidden" })
),
state("expanded", style({ height: "*", visibility: "visible" })),
transition(
"expanded <=> collapsed",
animate("225ms cubic-bezier(0.4, 0.0, 0.2, 1)")
)
])
]
})
export class JobExecutionScreenComponent implements OnInit {
displaySpinner: boolean = false;
jobId: string;
jobExecutionList: MatTableDataSource<any>;
jobExecStatDisplayedColumns = [
"jobId",
"executionDate",
"previousTimePeriod",
"afterTimePeriod",
"status",
"actions",
"spinner"
];
public selectedElem: any;
projectjobId: any = 1;
jobExecutionStat: any;
executionDate: string = new Date().toISOString().slice(0, 10);
executeJobStop: any;
changeStatus: any;
newStatus: any;
isExpansionDetailRow = (i: number, row: Object) =>
row.hasOwnProperty("detailRow");
expandedElement: any;
constructor(
private dataService: DataService,
public globalAppSateService: GlobalAppSateService,
private snakbar: SnakBarComponent,
private recommendationService: RecommendationService,
private messageService: MessageService
) {}
ngOnInit() {
const project = JSON.parse(this.dataService.getObject("project"));
if (project != null) {
this.globalAppSateService.onMessage(project);
}
// API to get list of Running Jobs
this.recommendationService
.getJobExecutionStatList(this.projectjobId)
.subscribe(data => {
this.jobExecutionList = new MatTableDataSource(data);
console.log(this.jobExecutionList);
// this.jobExecutionStat = new ExampleDataSource();
});
}
applyFilter(filterValue: string) {
this.jobExecutionList.filter = filterValue.trim().toLowerCase();
}
I already have an example for this kind, you can look over this.
Mat-Table-stackblitz
This code throws an error in the method of "populateGridRows()", at the line of “row.setCompuetedProperties();”. The error message is – “ERROR TypeError: row.setCompuetedProperties is not a function”.
I can see all the properties (with data) on the “row” object in the console just before I get the error.
As far as I can understand it is all about mapping the JSON data coming from the server into a class. Please let me know where I have made a mistake. Thanks.
delivery-plan.component.ts
import { Component, OnInit, ViewChild, ViewEncapsulation } from "#angular/core";
import { ActivatedRoute } from "#angular/router";
import { DetailRow, ExcelExportProperties, FilterSettingsModel, Grid, GridComponent, GridLine, PdfExportProperties } from "#syncfusion/ej2-ng-grids";
import { ClickEventArgs } from '#syncfusion/ej2-ng-navigations';
import { UtilService } from "../../../shared/services/util.service";
import { ConditionBasedMaintenanceStatusEnum } from "../../enums";
import { ConditionAssessmentService, IConditionBasedMaintenanceRowModel } from "../../services/conditionassessment.service";
import { DeliveryPlanModel, DeliveryPlanService, IDeliveryPlanModel } from "../../services/delivery-plan.service";
#Component({
encapsulation: ViewEncapsulation.None,
selector: 'app-delivery-plan',
templateUrl: './delivery-plan.component.html',
styleUrls: ['./delivery-plan.component.scss']
})
export class DeliveryplanComponent implements OnInit {
schoolNumber: number;
deliveryPlanItems: DeliveryPlanModel[];
componentVariables: ConditionAssessmentComponentVariables;
gridRows: Array<DeliveryPlanModel>;
#ViewChild("deliveryItemsGrid") deliveryItemsGrid: GridComponent;
progressValue1 = 100;
progressValue2 = 62;
clickedYear = null;
constructor(private route: ActivatedRoute, private svcConditionAssessment: ConditionAssessmentService,
private svcUtil: UtilService, private deliveryPlanService: DeliveryPlanService) {
this.componentVariables = new ConditionAssessmentComponentVariables();
this.gridRows = new Array<DeliveryPlanModel>();
}
ngOnInit() {
this.route.parent.params.subscribe(params => {
this.schoolNumber = parseInt(params["id"]);
});
Grid.Inject(DetailRow);
this.getDeliveryPlanItems();
}
public getDeliveryPlanItems() {
this.deliveryPlanService
.getDeliveryPlanItems(this.schoolNumber.toString()).subscribe(
data => {
if (data) {
this.deliveryPlanItems = data;
this.populateGridRows();
}
}
)
}
public populateGridRows(): void {
if (this.deliveryPlanItems && this.deliveryPlanItems.length) {
for (var i = 0; i < this.deliveryPlanItems.length; i++) {
let row = this.deliveryPlanItems[i];
console.log(row);
row.setCompuetedProperties(); // The Error is associated with this line
this.gridRows.push(row);
}
}
}
delivery-plan.service.ts
import { HttpClient, HttpHeaders, HttpParams } from "#angular/common/http";
import { Injectable } from "#angular/core";
import { Router } from '#angular/router';
import { Observable, Operator } from "rxjs";
import { ErrorsService } from "../../shared/services/errors.service";
import { ConditionBasedMaintenanceStatusEnum } from "../enums";
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};
export interface IDeliveryPlanModel {
//Props
type: string;
id: number;
buildingName: string;
location: string;
asset: string;
element: string;
subElement: string;
description: string;
trade: string;
status: number;
statusDisplay: string;
plannedDate: Date;
completedDate: Date;
deferred: boolean;
// methods
setCompuetedProperties(): void;
}
export class DeliveryPlanModel implements IDeliveryPlanModel {
//Props
type: string = null;
id: number = null;
buildingName: string = null;
location: string = null;
asset: string = null;
element: string = null;
subElement: string = null;
description: string = null;
trade: string = null;
status: number = null;
statusDisplay: string = null;
plannedDate: Date = null;
completedDate: Date = null;
deferred: boolean = null;
color: string = null;
// methods
public setCompuetedProperties(): void {
switch (this.status) {
case ConditionBasedMaintenanceStatusEnum.AddedToPlanner:
this.statusDisplay = "Planned";
break;
case ConditionBasedMaintenanceStatusEnum.Deferred:
this.statusDisplay = "Deferred";
break;
case ConditionBasedMaintenanceStatusEnum.Completed:
this.statusDisplay = "Completed";
break;
}
}
}
#Injectable()
export class DeliveryPlanService {
routePrefix: string = "api/deliveryplans";
constructor(private http: HttpClient, private router: Router, private errorsService: ErrorsService) { }
public getDeliveryPlanItems(schoolId: string): Observable<DeliveryPlanModel[]> {
var list = this.http.get<DeliveryPlanModel[]>(this.routePrefix + "/schools/" + schoolId)
.map<DeliveryPlanModel[], DeliveryPlanModel[]>(items => {
return items;
}).catch(error => this.errorsService.handleError(error));
return list;
}
}