ERROR TypeError: _co.saveXML is not a function
ERROR TypeError: _co.saveXML is not a function
在我的客户 Angular 项目中,我有一个名为 report-viewer 的组件。我在里面有一个表单,EmailSettings,当按下组件的按钮时调用它。
表单代码如下:
EmailSettings.html
<h1 mat-dialog-title>Email Settings</h1>
<div mat-dialog-content>
<form id="formID" class="example-form">
<mat-form-field *ngIf="data.smtpHost === ''" class="example-full-width" appearance="fill">
<mat-label>SMTP Host</mat-label>
<textarea matInput placeholder="Ex: smtp.gmail.com"></textarea>
</mat-form-field> <br>
<mat-form-field *ngIf="data.smtpPort === ''" class="example-full-width" appearance="fill">
<mat-label>SMTP Port</mat-label>
<textarea matInput placeholder="Ex: 587"></textarea>
</mat-form-field> <br>
<mat-form-field *ngIf="data.smtpUserName === ''" class="example-full-width" appearance="fill">
<mat-label>SMTP User Name</mat-label>
<textarea matInput placeholder="Ex: example@gmail.com"></textarea>
</mat-form-field> <br>
<mat-form-field *ngIf="data.smtpUserPassword === ''" class="example-full-width" appearance="fill">
<mat-label>SMTP User Password</mat-label>
<textarea matInput placeholder="Ex: password"></textarea>
</mat-form-field> <br>
<mat-form-field *ngIf="data.smtpFrom === ''" class="example-full-width" appearance="fill">
<mat-label>SMTP From</mat-label>
<textarea matInput placeholder="Ex: example@gmail.com"></textarea>
</mat-form-field> <br>
<mat-form-field *ngIf="data.smtpDisplayName === ''" class="example-full-width" appearance="fill">
<mat-label>SMTP Display Name</mat-label>
<textarea matInput placeholder="Ex: Jhon"></textarea>
</mat-form-field> <br>
<button mat-button (click)="saveXML()">Save</button>
<!-- <mat-form-field class="example-full-width" appearance="fill">
<button mat-button (click)="saveXML()">Save</button>
</mat-form-field> -->
</form>
</div>
EmailSettings.ts
import { Component, OnInit, ViewChild, ViewEncapsulation, ChangeDetectorRef, Inject } from '@angular/core';
import * as FileSaver from 'file-saver';
import { MatInputModule } from '@angular/material/input';
@Component({
selector: 'app-EmailSettings',
encapsulation: ViewEncapsulation.None,
templateUrl: './EmailSettings.html',
})
export class EmailSettings{
appIdOpts: any = [];
saveXML(){
console.log("TestXML");
let blob = new Blob([document.getElementById('formID').innerHTML], {type: "text/xml"});
FileSaver.saveAs(blob, "blobExport.xml");
}
}
当我按下表单的“保存”按钮时,出现错误 ERROR TypeError: _co.saveXML is not a function
。
我知道已经有了,但是没有帮我解决错误。我能做什么?
编辑:
正如@SirOneOfMany 所建议的,我创建了一个新组件 EmailSettings。我的新结构如下:
根据您的要求,我的报告-viewer.component.ts有以下内容。请注意,它包含一些与本主题无关的其他功能。与我们相关的函数称为 openDialog()
.
import { Component, OnInit, ViewChild, ViewEncapsulation, ChangeDetectorRef, Inject } from '@angular/core';
import 'devexpress-reporting/dx-richedit';
import { DxReportViewerComponent } from 'devexpress-reporting-angular';
import { HttpClient } from '@angular/common/http';
import DevExpress from '@devexpress/analytics-core';
import List from "devextreme/ui/list";
import { DxSelectBoxModule, DxCheckBoxModule, DxListModule } from 'devextreme-angular';
import { ParagraphPropertiesKeepLinesTogetherDescriptor } from 'devexpress-richedit/lib/core/model/paragraph/paragraph-property-descriptors';
import { DxDropDownBoxModule, DxTreeViewModule, DxDataGridModule, DxTreeViewComponent, } from 'devextreme-angular';
import DXAnalytics from '@devexpress/analytics-core/dx-analytics-core'
import * as ko from 'knockout';
import { MatDialog, MAT_DIALOG_DATA } from '@angular/material';
import { MatInputModule } from '@angular/material/input';
import { EmailSettingsComponent } from '../email-settings/email-settings.component';
@Component({
selector: 'app-report-viewer',
encapsulation: ViewEncapsulation.None,
templateUrl: './report-viewer.component.html',
styleUrls: [
"./report-viewer.component.css",
"../../../node_modules/jquery-ui/themes/base/all.css",
"../../../node_modules/devextreme/dist/css/dx.common.css",
"../../../node_modules/devextreme/dist/css/dx.light.css",
"../../../node_modules/@devexpress/analytics-core/dist/css/dx-analytics.common.css",
"../../../node_modules/@devexpress/analytics-core/dist/css/dx-analytics.light.css",
"../../../node_modules/devexpress-reporting/dist/css/dx-webdocumentviewer.css"
]
})
export class ReportViewerComponent implements OnInit {
@ViewChild(DxReportViewerComponent, { static: true }) viewer: DxReportViewerComponent;
@ViewChild('selectedReport', { static: false }) public selectedReport: "C:\ReportDesigner\Reports";
@ViewChild("emailSettings", { static: true }) emailSettings: EmailSettingsComponent;
// @ViewChild('selectedReport', { static: false }) public selectedReport: "@/Reports";
treeBoxValue: 'selectedReport';
isTreeBoxOpened: boolean;
title = 'DXReportViewerSample';
hostUrl = 'http://localhost:54111/';
invokeAction: string = "/WebDocumentViewer/Invoke";
reportUrl: string = 'Employee';
//some other functions here...
ngOnInit() {
var ajaxSetup = DXAnalytics.Analytics.Utils.ajaxSetup
ajaxSetup.ajaxSettings = {
xhrFields: {
withCredentials: true
}
};
}
openDialog(){ //this functions is used to open the form which was on EmailSettings.html)
this.dialog.open(EmailSettingsComponent, {
data: {
// animal: 'panda',
smtpHost: '',
smtpPort: '',
smtpUserName: '',
smtpUserPassword: '',
smtpFrom: '',
smtpDisplayName: '',
},
});
}
}
export interface DialogData {
smtpHost: any;
smtpPort: any;
smtpUserName: any;
smtpUserPassword: any;
smtpFrom: any;
smtpDisplayName: any;
}
@Component({
selector: 'app-email-settings',
templateUrl: 'email-settings',
})
export class EmailSettings {
constructor(@Inject(MAT_DIALOG_DATA) public data: DialogData) {}
}
此时我得到错误ERROR in ./src/app/report-viewer/report-viewer.component.ts Module not found: Error: Can't resolve './email-settings' in 'C:\ProiectVisualStudio\ProjectName\JS\angular-report-designer\src\app\report-viewer'
正如我在评论部分所述,您必须声明一个组件。仅仅添加一个装饰器是不够的。
每添加一个 class @Component(...) 都需要添加到模块的声明数组中。
我假设您只有一个 AppModule class。所以你需要将你的组件添加到这个模块。
你用过
@Component({
selector: 'app-EmailSettings',
encapsulation: ViewEncapsulation.None,
templateUrl: './EmailSettings.html',
})
因此您需要将 EmailSettings class 添加到您的模块声明数组中:
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent, ReportViewerComponent, EmailSettings ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
这就是为什么我说你应该用 ng 原理图创建你的组件,因为 angular 已经为你做了。
所以只需使用:
ng generate component relative/path/in/src/folder/email-settings
此命令将为您的组件创建文件(.ts、.html、.(s)css、.spec.ts)并将组件添加到最近的模块.
查看at this article以获得关于模块的更准确的解释
编辑
感谢您编辑您的问题。在 report-viewer 组件的最后,您有以下可能会引发错误的内容
@Component({
selector: 'app-email-settings',
templateUrl: 'email-settings', // this should throw the error
})
export class EmailSettings {
constructor(@Inject(MAT_DIALOG_DATA) public data: DialogData) {}
}
删除 class 并使用新生成的组件。作为一个小的最佳实践提示:
只需实现一个 class 通过每个文件的 @Component 装饰
使用 ng schematics 生成代码,这样你就可以确保你的东西在整个应用程序中是一致的。
为每个接口提供一个文件并将其移动到模型文件夹
在我的客户 Angular 项目中,我有一个名为 report-viewer 的组件。我在里面有一个表单,EmailSettings,当按下组件的按钮时调用它。
表单代码如下:
EmailSettings.html
<h1 mat-dialog-title>Email Settings</h1>
<div mat-dialog-content>
<form id="formID" class="example-form">
<mat-form-field *ngIf="data.smtpHost === ''" class="example-full-width" appearance="fill">
<mat-label>SMTP Host</mat-label>
<textarea matInput placeholder="Ex: smtp.gmail.com"></textarea>
</mat-form-field> <br>
<mat-form-field *ngIf="data.smtpPort === ''" class="example-full-width" appearance="fill">
<mat-label>SMTP Port</mat-label>
<textarea matInput placeholder="Ex: 587"></textarea>
</mat-form-field> <br>
<mat-form-field *ngIf="data.smtpUserName === ''" class="example-full-width" appearance="fill">
<mat-label>SMTP User Name</mat-label>
<textarea matInput placeholder="Ex: example@gmail.com"></textarea>
</mat-form-field> <br>
<mat-form-field *ngIf="data.smtpUserPassword === ''" class="example-full-width" appearance="fill">
<mat-label>SMTP User Password</mat-label>
<textarea matInput placeholder="Ex: password"></textarea>
</mat-form-field> <br>
<mat-form-field *ngIf="data.smtpFrom === ''" class="example-full-width" appearance="fill">
<mat-label>SMTP From</mat-label>
<textarea matInput placeholder="Ex: example@gmail.com"></textarea>
</mat-form-field> <br>
<mat-form-field *ngIf="data.smtpDisplayName === ''" class="example-full-width" appearance="fill">
<mat-label>SMTP Display Name</mat-label>
<textarea matInput placeholder="Ex: Jhon"></textarea>
</mat-form-field> <br>
<button mat-button (click)="saveXML()">Save</button>
<!-- <mat-form-field class="example-full-width" appearance="fill">
<button mat-button (click)="saveXML()">Save</button>
</mat-form-field> -->
</form>
</div>
EmailSettings.ts
import { Component, OnInit, ViewChild, ViewEncapsulation, ChangeDetectorRef, Inject } from '@angular/core';
import * as FileSaver from 'file-saver';
import { MatInputModule } from '@angular/material/input';
@Component({
selector: 'app-EmailSettings',
encapsulation: ViewEncapsulation.None,
templateUrl: './EmailSettings.html',
})
export class EmailSettings{
appIdOpts: any = [];
saveXML(){
console.log("TestXML");
let blob = new Blob([document.getElementById('formID').innerHTML], {type: "text/xml"});
FileSaver.saveAs(blob, "blobExport.xml");
}
}
当我按下表单的“保存”按钮时,出现错误 ERROR TypeError: _co.saveXML is not a function
。
我知道已经有
编辑:
正如@SirOneOfMany 所建议的,我创建了一个新组件 EmailSettings。我的新结构如下:
根据您的要求,我的报告-viewer.component.ts有以下内容。请注意,它包含一些与本主题无关的其他功能。与我们相关的函数称为 openDialog()
.
import { Component, OnInit, ViewChild, ViewEncapsulation, ChangeDetectorRef, Inject } from '@angular/core';
import 'devexpress-reporting/dx-richedit';
import { DxReportViewerComponent } from 'devexpress-reporting-angular';
import { HttpClient } from '@angular/common/http';
import DevExpress from '@devexpress/analytics-core';
import List from "devextreme/ui/list";
import { DxSelectBoxModule, DxCheckBoxModule, DxListModule } from 'devextreme-angular';
import { ParagraphPropertiesKeepLinesTogetherDescriptor } from 'devexpress-richedit/lib/core/model/paragraph/paragraph-property-descriptors';
import { DxDropDownBoxModule, DxTreeViewModule, DxDataGridModule, DxTreeViewComponent, } from 'devextreme-angular';
import DXAnalytics from '@devexpress/analytics-core/dx-analytics-core'
import * as ko from 'knockout';
import { MatDialog, MAT_DIALOG_DATA } from '@angular/material';
import { MatInputModule } from '@angular/material/input';
import { EmailSettingsComponent } from '../email-settings/email-settings.component';
@Component({
selector: 'app-report-viewer',
encapsulation: ViewEncapsulation.None,
templateUrl: './report-viewer.component.html',
styleUrls: [
"./report-viewer.component.css",
"../../../node_modules/jquery-ui/themes/base/all.css",
"../../../node_modules/devextreme/dist/css/dx.common.css",
"../../../node_modules/devextreme/dist/css/dx.light.css",
"../../../node_modules/@devexpress/analytics-core/dist/css/dx-analytics.common.css",
"../../../node_modules/@devexpress/analytics-core/dist/css/dx-analytics.light.css",
"../../../node_modules/devexpress-reporting/dist/css/dx-webdocumentviewer.css"
]
})
export class ReportViewerComponent implements OnInit {
@ViewChild(DxReportViewerComponent, { static: true }) viewer: DxReportViewerComponent;
@ViewChild('selectedReport', { static: false }) public selectedReport: "C:\ReportDesigner\Reports";
@ViewChild("emailSettings", { static: true }) emailSettings: EmailSettingsComponent;
// @ViewChild('selectedReport', { static: false }) public selectedReport: "@/Reports";
treeBoxValue: 'selectedReport';
isTreeBoxOpened: boolean;
title = 'DXReportViewerSample';
hostUrl = 'http://localhost:54111/';
invokeAction: string = "/WebDocumentViewer/Invoke";
reportUrl: string = 'Employee';
//some other functions here...
ngOnInit() {
var ajaxSetup = DXAnalytics.Analytics.Utils.ajaxSetup
ajaxSetup.ajaxSettings = {
xhrFields: {
withCredentials: true
}
};
}
openDialog(){ //this functions is used to open the form which was on EmailSettings.html)
this.dialog.open(EmailSettingsComponent, {
data: {
// animal: 'panda',
smtpHost: '',
smtpPort: '',
smtpUserName: '',
smtpUserPassword: '',
smtpFrom: '',
smtpDisplayName: '',
},
});
}
}
export interface DialogData {
smtpHost: any;
smtpPort: any;
smtpUserName: any;
smtpUserPassword: any;
smtpFrom: any;
smtpDisplayName: any;
}
@Component({
selector: 'app-email-settings',
templateUrl: 'email-settings',
})
export class EmailSettings {
constructor(@Inject(MAT_DIALOG_DATA) public data: DialogData) {}
}
此时我得到错误ERROR in ./src/app/report-viewer/report-viewer.component.ts Module not found: Error: Can't resolve './email-settings' in 'C:\ProiectVisualStudio\ProjectName\JS\angular-report-designer\src\app\report-viewer'
正如我在评论部分所述,您必须声明一个组件。仅仅添加一个装饰器是不够的。 每添加一个 class @Component(...) 都需要添加到模块的声明数组中。
我假设您只有一个 AppModule class。所以你需要将你的组件添加到这个模块。
你用过
@Component({
selector: 'app-EmailSettings',
encapsulation: ViewEncapsulation.None,
templateUrl: './EmailSettings.html',
})
因此您需要将 EmailSettings class 添加到您的模块声明数组中:
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent, ReportViewerComponent, EmailSettings ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
这就是为什么我说你应该用 ng 原理图创建你的组件,因为 angular 已经为你做了。
所以只需使用:
ng generate component relative/path/in/src/folder/email-settings
此命令将为您的组件创建文件(.ts、.html、.(s)css、.spec.ts)并将组件添加到最近的模块.
查看at this article以获得关于模块的更准确的解释
编辑
感谢您编辑您的问题。在 report-viewer 组件的最后,您有以下可能会引发错误的内容
@Component({
selector: 'app-email-settings',
templateUrl: 'email-settings', // this should throw the error
})
export class EmailSettings {
constructor(@Inject(MAT_DIALOG_DATA) public data: DialogData) {}
}
删除 class 并使用新生成的组件。作为一个小的最佳实践提示:
只需实现一个 class 通过每个文件的 @Component 装饰
使用 ng schematics 生成代码,这样你就可以确保你的东西在整个应用程序中是一致的。
为每个接口提供一个文件并将其移动到模型文件夹