https://i.sstatic.net/hghse.png
My goal is to develop a dynamic filtering system where users can specify multiple attributes and their corresponding values to filter a list of components. The dynamically added component includes two dropdown menus: one for attribute selection and another for attribute values. There is also an 'Add' button to add the next attribute filter component. The attribute list is filtered based on a selected catalog passed through an @Input. Here's how the pieces of this puzzle come together:
In the parent HTML document, the attribute filter container is included:
<app-attribute-filter-container [catalogSelected]="catalog"></app-attribute-filter-container>
The current setup of the attribute filter container involves an ng-template with a dynamic placeholder:
<ng-template #dynamic></ng-template>
Below is the TypeScript code for the container:
import { Component, NgModule, Inject, OnInit, ViewChild, ViewContainerRef, Input } from '@angular/core';
import { AttributeFilterCreatorService } from '../../services/attribute-filter-creator.service';
import { Catalog } from '../../interfaces/interfaces';
@Component({
selector: 'app-attribute-filter-container',
templateUrl: './attribute-filter-container.component.html',
styleUrls: ['./attribute-filter-container.component.css'],
providers: [AttributeFilterCreatorService]
})
export class AttributeFilterContainerComponent {
@Input() catalogSelected: Catalog;
service: AttributeFilterCreatorService;
@ViewChild('dynamic', {
read: ViewContainerRef
}) viewContainerRef: ViewContainerRef
constructor(@Inject(AttributeFilterCreatorService) service) {
this.service = service;
}
ngOnInit() {
console.log('Container Catalog: ', this.catalogSelected);
this.service.setRootViewContainerRef(this.viewContainerRef);
this.service.addDynamicComponent();
}
}
Lastly, here is the TypeScript code for the attribute filter component:
import { Component, OnInit, ViewEncapsulation, Input, Inject } from '@angular/core';
import { Attribute, AttributeValue, Catalog } from '../../interfaces/interfaces';
import { HttpClient, HttpHeaders, HttpRequest, HttpEventType } from '@angular/common/http';
import { Router } from '@angular/router';
import { AuthService } from '../../services/auth.service';
@Component({
selector: 'app-attribute-filter',
templateUrl: './attribute-filter.component.html',
styleUrls: ['./attribute-filter.component.css'],
encapsulation: ViewEncapsulation.None
})
export class AttributeFilterComponent implements OnInit {
@Input() catalogSelected: Catalog;
@Input() attributes: Attribute[];
attributeValues: AttributeValue[];
urlBase: string = "";
selectedAttribute: Attribute;
constructor(private auth: AuthService, private http: HttpClient, private router: Router, @Inject('BASE_URL') baseUrl: string) {
this.urlBase = baseUrl;
}
ngOnInit() {
if (!this.attributes) {
this.LoadAttributes();
}
}
attributeSelect(selectedAttribute) {
this.LoadAttributeValues(selectedAttribute.id);
}
private LoadAttributes() {
var attUrl = this.urlBase + 'api/Attribute/Attributes/' + this.catalogSelected.catalogcode;
console.log("LOAD ATTRIBUTES", attUrl);
this.http.get<Attribute[]>(attUrl).subscribe(result => {
if (result.length == 0) {
this.auth.logout();
this.router.navigate(["login"]);
}
else {
this.attributes = result;
}
}, error => console.error(error));
}
private LoadAttributeValues(attributeid) {
this.attributeValues = [];
var attValUrl = this.urlBase + 'api/Attribute/AttributeValues/' + this.catalogSelected.catalogcode + '/' + attributeid;
this.http.get<AttributeValue[]>(attValUrl).subscribe(result => {
if (result.length == 0) {
this.auth.logout();
this.router.navigate(["login"]);
}
else {
this.attributeValues = result;
}
}, error => console.error(error));
}
}
The value of catalogSelected does not get passed to the dynamically injected component, causing the attribute dropdown values not to load.