Angular Drag’n Drop With Query Components and Form Validation
The AngularPortfolioMgr project can import the SEC filings of listed companies. The importer class is the FileClientBean and imports the JSON archive from “Kaggle.”
The data is provided by year, symbol, and period. Each JSON data set has keys (called concepts) and values with the USD value. For example, IBM’s full-year revenue in 2020 was $13,456.
This makes two kinds of searches possible. A search for company data and a search for keys (concepts) over all entries.
The components below “Company Query” select the company value year with operators like “=,” “>=,” and “<=” (values less than 1800 are ignored). The symbol search is implemented with an angular autocomplete component that queries the backend for matching symbols. The quarters are in a select component of the available periods.
@Component({
selector: “app-create-query”,
templateUrl: “./create-query.component.html”,
styleUrls: [“./create-query.component.scss”],
})
export class CreateQueryComponent implements OnInit, OnDestroy {
private subscriptions: Subscription[] = [];
private readonly availableInit: MyItem[] = [
…
];
protected readonly availableItemParams = {
…
} as ItemParams;
protected readonly queryItemParams = {
…
} as ItemParams;
protected availableItems: MyItem[] = [];
protected queryItems: MyItem[] = [
…
];
protected queryForm: FormGroup;
protected yearOperators: string[] = [];
protected quarterQueryItems: string[] = [];
protected symbols: Symbol[] = [];
protected FormFields = FormFields;
protected formStatus = ”;
@Output()
symbolFinancials = new EventEmitter<SymbolFinancials[]>();
@Output()
financialElements = new EventEmitter<FinancialElementExt[]>();
@Output()
showSpinner = new EventEmitter<boolean>();
constructor(
private fb: FormBuilder,
private symbolService: SymbolService,
private configService: ConfigService,
private financialDataService: FinancialDataService
) {
this.queryForm = fb.group(
{
[FormFields.YearOperator]: “”,
[FormFields.Year]: [0, Validators.pattern(“^\d*$”)],
[FormFields.Symbol]: “”,
[FormFields.Quarter]: [“”],
[FormFields.QueryItems]: fb.array([]),
}
, {
validators: [this.validateItemTypes()]
}
);
this.queryItemParams.formArray = this.queryForm.controls[
FormFields.QueryItems
] as FormArray;
//delay(0) fixes “NG0100: Expression has changed after it was checked” exception
this.queryForm.statusChanges.pipe(delay(0)).subscribe(result => this.formStatus = result);
}
ngOnInit(): void {
this.symbolFinancials.emit([]);
this.financialElements.emit([]);
this.availableInit.forEach((myItem) => this.availableItems.push(myItem));
this.subscriptions.push(
this.queryForm.controls[FormFields.Symbol].valueChanges
.pipe(
debounceTime(200),
switchMap((myValue) => this.symbolService.getSymbolBySymbol(myValue))
)
.subscribe((myValue) => (this.symbols = myValue))
);
this.subscriptions.push(
this.configService.getNumberOperators().subscribe((values) => {
this.yearOperators = values;
this.queryForm.controls[FormFields.YearOperator].patchValue(
values.filter((myValue) => myValue === “=”)[0]
);
})
);
this.subscriptions.push(
this.financialDataService
.getQuarters()
.subscribe(
(values) =>
(this.quarterQueryItems = values.map((myValue) => myValue.quarter))
)
);
}