简体   繁体   English

属性绑定问题Angular 4

[英]Property binding issue Angular 4

I am working on Angular 4 upgrade and having few niggling issues. 我正在进行Angular 4升级,很少有麻烦的问题。 I am getting the following error and not sure what the problem is. 我收到以下错误,不确定是什么问题。 I can see the reference to the module statement-selector.component in risk-tolerance-statements.component 我可以在Risk-tolerance-statements.component中看到对模块statement-selector.component的引用

The error is as follows 错误如下

Can't bind to 'riskToleranceStatements' since it isn't a known property of 'rtq-statement-selector'.
1. If 'rtq-statement-selector' is an Angular component and it has 'riskToleranceStatements' input, then verify that it is part of this module.
2. If 'rtq-statement-selector' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. ("   <rtq-statement-selector *ngIf="showStatementSelectPopup"

risk-tolerance-statements.component 风险容忍声明

import {Component, ViewChild, EventEmitter,ViewContainerRef} from '@angular/core';
import { RunService,ClientService,UserService,AnalyticsService,ModalService} from '@wtw/platform/services';
import { Dto} from '@wtw/platform/api';
import {Observable} from 'rxjs/rx';
import { IAnalyticsSendInput} from '@wtw/platform/interfaces';
import { Base,ChangeTracking as CT} from '@wtw/toolkit';
//import {PdfLinkDirective} from '@wtw/toolkit/directives';
import {Indexer} from '../../interfaces/indexer';
import {OptionsSelectorComponent} from './options-selector/options-selector.component';
import {OptionDisplayComponent} from './option-display/option-display.component';
import {OptionSectionDisplayComponent} from './option-section-display/option-section-display.component';
import {StatementSelectorComponent} from './statement-selector/statement-selector.component';
import {RunViewModel, StatementOption, Metric} from '../../api/generated/RunViewModel';
import {OnForwardNavigation} from '@wtw/platform/interfaces';
import {MetricChartComponent} from '../../shared/charts/metric-chart.component';
import {CoreModalComponent} from '@wtw/platform/components/core-modal/core-modal.component';



@Component({
    moduleId: module.id,
    templateUrl: 'risk-tolerance-statements.component.html',
    styleUrls: ['../../shared/style/site.css', '../../styles/rtc.css']
})
export class RiskToleranceStatementsComponent extends Base.ReactiveComponent implements OnForwardNavigation {

    metricMap: Indexer<Metric> = {};
    runInformation: Dto.RunInfo;
    runModel: RunViewModel;
    selectedOption: StatementOption;
    metricChartOptions: any = JSON.parse("{ \"chart\": { \"height\":260, \"type\":\"scatter\",\"marginTop\":30 },\"title\": { \"text\": \"\"}, \"legend\": {\"enabled\":false},\"credits\": {\"enabled\": false},\"series\": [{},{ \"type\": \"scatter\", \"marker\": {\"enabled\": false}}], \"xAxis\":{\"endOnTick\": true, \"startOnTick\": true, \"minPadding\": 0.2, \"maxPadding\": 0.2,\"labels\":{\"enabled\":true},\"gridLineWidth\": 0,\"gridLineColor\": \"black\",\"minorGridLineWidth\": 0,\"tickColor\": \"black\",\"title\":{\"text\":\"Size of Loss\",\"useHtml\":true}}, \"yAxis\":{\"startOnTick\":true,\"tickInterval\":5, \"endOnTick\":true,\"min\":0,\"labels\":{\"enabled\":true},\"title\": {\"text\": \"Metric Scores Before Loss\",\"useHtml\":true,\"align\":\"high\",\"rotation\":0,\"y\":-15,\"offset\":-110}}, \"plotOptions\": { \"scatter\": {\"marker\": { \"radius\": 15,\"enabled\": true}}},\"tooltip\": {\"enabled\":true,\"pointFormat\": \"score:{point.y}value:{point.x}\"} }");
    riskToleranceStatementChartOptions: any = {
        showSlider: false,
        showPlotLineLabel: true,
        isStressTest: false
    };

    selectedStatementOptionDisplay: StatementOption;
    showStatementSelectPopup = false;
    showModifyOptionPopup = false;
    statementsSelectedEvent = new EventEmitter<any>();
    statementsSelectedObservable: () => Promise<any>;
    riskToleranceStatements: StatementOption[];
    bellCurveChartData: any = {};
    selectedOptionId: number;
    selectedComment: StatementOption;
    currencyInformation: Dto.CurrencyInfo;

    @ViewChild(MetricChartComponent) private metricChartComponent: MetricChartComponent;
    //@ViewChild(PdfLinkDirective) private pdfDirective: PdfLinkDirective;

    constructor(private viewRef:ViewContainerRef,public runService: RunService, private _modalService: ModalService, private googleAnalyticSevice: AnalyticsService, private clients: ClientService, private user: UserService) { super(); }

    ngOnInit() {
        const runServiceSubscription = this.runService.activeRun
            .filter((run: any) => !!run)
            .subscribe((run: any) => {
                this.runInformation = run.info;
                this.currencyInformation = run.currencyInfo;
                this.updateRunModel(run.data);
                this.bellCurveChartData = {
                    options: run.data.chartDefinitions.metricPickerChartOptions,
                    data: run.data.chartDefinitions.bellCurveChartData
                }
            });

        this._subscriptions.push(runServiceSubscription);
        this.statementsSelectedObservable = this.getstatementSeletedObservable;
        this.triggerGoogleAnanlyticsEvent();
    }

    reload(run: RunViewModel) { // After currency change
        this.updateRunModel(run);
        this.metricChartComponent.reloadChart(run);
        this.updateSelectedRiskToleranceThreshold();
    }

    apply() {
        this.runService.executeTrigger(this.runInformation.runId, this.runModel, 3, this.currencyInformation, 'risk-tolerance-statements');
        this.triggerGoogleAnanlyticsEvent();
    }

    /**
     * Function to push to the platform to be envoked when the pdf button is clicked.
     * The promise chain to be resolved with statement selector popup close event
     */
    getstatementSeletedObservable = () => {

        const applyOptionIdsPromise: Promise<any> = new Promise((resolve: any) => {
            this.runModel.riskToleranceStatements.options = this.riskToleranceStatements
                .map((option: StatementOption, index: number) => {
                    option.id = index;
                    return option;
                });
            resolve();
        });

        const saveRunPromise: Promise<any> = this.runService
            .persist(this.runInformation.runId, this.runModel, this.currencyInformation, null, true)
            .do(() => this.showStatementSelectPopup = true)
            .do(() => console.debug('Run saved'))
            .toPromise();

        const selectedStatementEventPromise = this.statementsSelectedEvent.take(1).toPromise();

        return Promise.all([applyOptionIdsPromise, saveRunPromise, selectedStatementEventPromise])
            .then((retVals) => retVals[2]);

    };

    optionSelected(option: StatementOption) {
        this.riskToleranceStatements.map((statement: StatementOption) => {
            statement.selected = statement.id === option.id;
        });
        this.refresh();
    }

    optionRemoved(option: StatementOption) {
        this._modalService.confirm(this.viewRef,'MODAL.TEST')
            .then((shouldRemove: boolean) => {
                if (shouldRemove) this.removeOption(option);
            });
    }

    statementsSelected(selectResult: any) {
        this.statementsSelectedEvent.emit(selectResult);
        this.showStatementSelectPopup = false;
    }

    showOptionDiplayPopup(statementOption?: StatementOption) {

        if (!statementOption) {
            statementOption = (Object.assign({}, this.runModel.riskToleranceStatements.vanillaOption) as StatementOption);
            statementOption.selected = false;
            statementOption.id = null; // New, unconfirmed option. No Id set until form complete
        }

        this.selectedStatementOptionDisplay = statementOption;
        this.showModifyOptionPopup = true;
    }

    optionChange(selectedOption: StatementOption) {

        this.showModifyOptionPopup = false;
        let runMatlabApply = false;

        if (!selectedOption) return; // cancelled change, just ignore

        this.riskToleranceStatements.map((option: StatementOption) => option.selected = false);
        selectedOption.selected = true;

        if (!selectedOption.id) {
            // new option
            selectedOption.id = (this.riskToleranceStatements.length + 1) || 1;
            this.riskToleranceStatements.push(selectedOption);
            runMatlabApply = true;
        } else {
            // modified option
            let selectedRiskToleranceIndex: number;
            const matchingOption = this.riskToleranceStatements.find((option: StatementOption, index: number) => {
                if (option.id !== selectedOption.id) return false;
                selectedRiskToleranceIndex = index;
                return true;
            });
            if (!matchingOption) throw new Error("Unable to find matching statement option from display");
            runMatlabApply = matchingOption.riskToleranceThreshold !== selectedOption.riskToleranceThreshold || matchingOption.selectedTimeHorizon !== selectedOption.selectedTimeHorizon;
            this.riskToleranceStatements[selectedRiskToleranceIndex] = selectedOption;
        }

        this.refresh();
        if (runMatlabApply) this.apply();
    }

    private updateRunModel(run: RunViewModel) {
        this.runModel = run;
        this.runModel.metrics.map(m => this.metricMap[m.id] = m);
        this.riskToleranceStatements = this.runModel.riskToleranceStatements.options || [];
        this.metricChartComponent.reloadChart(this.runModel);

        if (!this.riskToleranceStatements.length) return this.showOptionDiplayPopup();

        const selectedOption = this.riskToleranceStatements.find((option: StatementOption) => {
            return option.selected;
        });

        if (!selectedOption) {
            this.selectedOption = this.riskToleranceStatements[0];
            this.selectedOption.selected = true;
        }

        this.metricChartComponent.reloadChart(this.runModel);
        this.refresh();

    }

    private generateChartPlotlines(): any[] {

        const plotItems = this.riskToleranceStatements
            .filter((option: StatementOption) => {
                return !!option.riskToleranceThreshold;
            })
            .map((option: StatementOption, index: number) => {
                return {
                    value: option.riskToleranceThreshold,
                    label: index + 1,
                    focus: option.selected,
                    index: index
                };
            });

        return plotItems;
    }

    private removeOption(option: StatementOption) {
        if (option) {

            this.riskToleranceStatements = this.riskToleranceStatements.filter((statement: StatementOption) => {
                return statement.id !== option.id;
            });

            this.runModel.riskToleranceStatements.options = this.riskToleranceStatements.filter((statement: StatementOption) => {
                return statement.id !== option.id;
            });

            this.runService
                .persist(this.runInformation.runId, this.runModel, this.currencyInformation, null, true)
        }


        this.refresh();
    }

    private updateSelectedRiskToleranceThreshold() {
        this.riskToleranceStatements
            .filter((option) => option.selected)
            .map((option) => this.selectedOption = option);
    }

    private refresh() {
        this.reassignStatementIds();
        const chartPlotLines = this.generateChartPlotlines();
        this.metricChartComponent.refreshPlotlines(chartPlotLines);
       // if (this.pdfDirective) this.pdfDirective.beforeGenerate = this.getstatementSeletedObservable;
    }

    private reassignStatementIds() {
        this.riskToleranceStatements.map((option: StatementOption, index: number) => {
            option.id = index + 1;
        });
        var statements: StatementOption[] = JSON.parse(JSON.stringify(this.riskToleranceStatements));
        var actualSelected = statements.find(o => o.selected);
        var sorted = statements.sort((pre, curr) => pre.riskToleranceThreshold - curr.riskToleranceThreshold);
        this.selectedOptionId = sorted.indexOf(actualSelected) + 1;
        this.selectedComment = actualSelected;
        this.runModel.riskToleranceStatements.options = this.riskToleranceStatements;
    }

    onForwardNavigation(): void {
    }

    triggerGoogleAnanlyticsEvent() {
        let sendInput:IAnalyticsSendInput= {
            eventAction:'Risk Tolerance Statements Trigger',
            eventCategory:'Trigger',
            runId:this.runInformation.runId,
            addtionalFields:{
               user: this.user.currentUserInfo.encryptedUser, 
               clientId:this.runInformation.clientId
            }
        }
        this.googleAnalyticSevice.send(sendInput,true);
    }
}

statement-selector.component 语句选择器组件

import {EventEmitter, Output, Input, OnInit, Component} from '@angular/core'
//import {ToastsManager} from 'ng2-toastr'; 


import {StatementOption, SelectOption} from '../../../api/generated/RunViewModel';
import {RoundCheckboxComponent} from '../../../shared/round-checkbox/round-checkbox.component';

@Component({
    moduleId: module.id,
    selector: 'rtq-statement-selector',
    templateUrl: 'statement-selector.component.html',
  // directives: [
   //     RoundCheckboxComponent
   // ],
    styleUrls: ['statement-selector.component.css']
})
export class StatementSelectorComponent implements OnInit {

    statements: any[];

    @Input() maxStatements: number = 3;
    @Input() private riskToleranceStatements: StatementOption[] = [];
    @Output() complete: EventEmitter<any> = new EventEmitter<any>();

   // constructor(private toastr: ToastsManager) { }

    ngOnInit(): any {
        this.statements = this.riskToleranceStatements.map((statement: any, index: number): any[] => {
            const item = statement;
            item.isSelected = (index + 1) <= this.maxStatements;
            const selectedCompany = statement.company.find((company: SelectOption) => {
                return company.selected;
            });
            if (selectedCompany && selectedCompany.friendlyName) item.selectedCompany = selectedCompany.friendlyName;
            return item;
        });
    }

    cancelClicked() {
        this.complete.emit(false);
    }

    okClicked() {
        const selectedIds = this.statements
                .filter((statement: any) => statement.isSelected)
                .map((statement: any) => statement.id)
                .join(",");

        const selectedStatementIds = { selectedStatementIds: selectedIds };
        this.complete.emit(selectedStatementIds);
    }

    togs(statement: any) {
        const isSelected: boolean = statement.isSelected;

        const selectedCount = this.statements
            .filter((statement: any) => {
                return statement.isSelected;
            })
            .length;

        if (isSelected) {
            if (selectedCount <= 1) { return; }
        } else {
            if (this.maxStatements && selectedCount === this.maxStatements) { return; }
        }

        statement.isSelected = !isSelected;
    }
}

risk-tolerance-statements.component.html risk-tolerance-statements.component.html

<div id="pageConstrainer">

    <div class="grid" style="position: fixed; width: inherit; max-width: inherit; z-index: 5">
        <div class="col-dt-1 col-ipl-1 col-ipp-1" style="padding-right: 0px;">
            <!--<a pdf-link="risk-tolerance-statement-report" [runId]="runInformation?.runId" [beforeGenerate]="statementsSelectedObservable" style="display: block; position: absolute; right: 3px; top: 3px;"></a>-->
            <currency-selector (selectedCurrencyChange)="reload($event.run)"></currency-selector>
        </div>
    </div>

    <div class="grid grid-padded" style="padding-top: 32px;">

        <rtq-statement-selector *ngIf="showStatementSelectPopup" (complete)="statementsSelected($event)" [riskToleranceStatements]="riskToleranceStatements"></rtq-statement-selector>
        <rtq-option-display *ngIf="showModifyOptionPopup" [option]="selectedStatementOptionDisplay" [timeHorizons]="runModel?.riskToleranceStatements?.timeHorizons" (optionDisplayStatusChange)="optionChange($event)"></rtq-option-display>


        <div class="grid padded" style="background-color:#efeede;">
            <div class="col-dt-1 col-ipl-1 col-ipp-1 module">
                <div class="module-header">
                    {{'STRESS_TEST_PAGE.SIZE_OF_LOSS.HEADER'|translate}}
                    <template #sizeOfLossHtmlTooltip>
                        <span [innerHTML]="'TOOLTIPS.STRESS_TEST.SIZE_OF_LOSS'|translate"></span>
                    </template>
                    <span class="help" style="margin-top: -10px;" [tooltip]="sizeOfLossHtmlTooltip"></span>
                </div>
                <div class="module-content border" style="min-height: 260px; position: relative">
                    <metric-chart [runModel]="runModel" [options]="riskToleranceStatementChartOptions" [chartOptions]="metricChartOptions"></metric-chart>
                </div>
            </div>
        </div>

        <div class="grid padded">
            <div class="col-dt-1-4 col-ipl-1-4 col-ipp-1-4">
                <div class="sectionLabel left" [textContent]="'GENERAL.COMMENTS'|translate"></div>
                <br/>
                <br/>
                <rtq-options-selector (optionRemoved)="optionRemoved($event)" *ngIf="riskToleranceStatements" [vanillaOption]="runModel?.riskToleranceStatements?.vanillaOption" [options]="riskToleranceStatements" (optionSelected)="optionSelected($event)" (optionEditDisplayClick)="showOptionDiplayPopup($event)"></rtq-options-selector>
            </div>
            <div class="module col-dt-3-4 col-ipl-3-4 col-ipp-3-4">
                <div class="module">
                    <div class="module-header">
                        Area of Concern Score After Threshold Event(s)
                        <!--<span class="help" [tooltip]="'TOOLTIPS.STRESS_TEST.SIZE_OF_LOSS'|translate"></span>-->
                    </div>
                    <div class="module-content border">
                        <rtq-option-section-display [commentSections]="runModel?.commentSections" 
                                                    [sections]="runModel?.sections" 
                                                    [selectedCommentId]="selectedOptionId"
                                                    [selectedComment]="selectedComment"></rtq-option-section-display>
                    </div>
                </div>
            </div>
        </div>

    </div>

</div>

statement-selector-component.html statement-selector-component.html

import {EventEmitter, Output, Input, OnInit, Component} from '@angular/core'
//import {ToastsManager} from 'ng2-toastr'; 


import {StatementOption, SelectOption} from '../../../api/generated/RunViewModel';
import {RoundCheckboxComponent} from '../../../shared/round-checkbox/round-checkbox.component';

@Component({
    moduleId: module.id,
    selector: 'rtq-statement-selector',
    templateUrl: 'statement-selector.component.html',
  // directives: [
   //     RoundCheckboxComponent
   // ],
    styleUrls: ['statement-selector.component.css']
})
export class StatementSelectorComponent implements OnInit {

    statements: any[];

    @Input() maxStatements: number = 3;
    @Input() private riskToleranceStatements: StatementOption[] = [];
    @Output() complete: EventEmitter<any> = new EventEmitter<any>();

   // constructor(private toastr: ToastsManager) { }

    ngOnInit(): any {
        this.statements = this.riskToleranceStatements.map((statement: any, index: number): any[] => {
            const item = statement;
            item.isSelected = (index + 1) <= this.maxStatements;
            const selectedCompany = statement.company.find((company: SelectOption) => {
                return company.selected;
            });
            if (selectedCompany && selectedCompany.friendlyName) item.selectedCompany = selectedCompany.friendlyName;
            return item;
        });
    }

    cancelClicked() {
        this.complete.emit(false);
    }

    okClicked() {
        const selectedIds = this.statements
                .filter((statement: any) => statement.isSelected)
                .map((statement: any) => statement.id)
                .join(",");

        const selectedStatementIds = { selectedStatementIds: selectedIds };
        this.complete.emit(selectedStatementIds);
    }

    togs(statement: any) {
        const isSelected: boolean = statement.isSelected;

        const selectedCount = this.statements
            .filter((statement: any) => {
                return statement.isSelected;
            })
            .length;

        if (isSelected) {
            if (selectedCount <= 1) { return; }
        } else {
            if (this.maxStatements && selectedCount === this.maxStatements) { return; }
        }

        statement.isSelected = !isSelected;
    }
}

You riskToleranceStatements property is marked as private and as such cannot be used in a template. 您的riskToleranceStatements属性被标记为私有,因此不能在模板中使用。 The fix would be to make it a public property. 解决办法是使其成为公共财产。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM