我已经为此努力了很长时间。然而,我最终放弃并寻求社区的支持。预先感谢您的帮助!
我有使用网页组件的网络项目模块。我正在 Webprojects 模块中导入对象模块(具有导航栏组件和 ComponentLoaderDirective)。
&我正在尝试将 navbar.html 的内容加载到webpage.component.html
为什么 Angular 强迫我在 weboage.components.ts 中再次导入 NavbarComponent 和 ComponentLoaderDirective?如果没有相同的我会得到以下错误: 找不到名称“导航栏组件”。 找不到名称“ComponentLoaderDirective”。
我想我在这里遗漏了一些东西。只是无法找到丢失的东西。
webprojects.module.ts
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { Global } from '../../../class.global'; //Global Class Contains the Global Variables & Functions Being Used Throughout the Project.
import { StartupService } from 'src/app/services/shared/startup.service'; //StartupService is Used to Get the Project, Page, Object & Elements on Page Load.
import { ObjectsModule } from './objects/objects.module';
import { WebpageComponent } from './webpage/webpage.component'; //WebProjectsModule Uses WebpageComponent as the View (webpage.component.html) & Controller (webpage.component.html).
@NgModule({
declarations: [WebpageComponent], //WebProject Module Uses the Webpage Component
imports: [HttpClientModule, ObjectsModule],
exports: [], //Webprojects Module Exports the Webpage Component to the App Module & Other Modules Using the WebProjects Module
providers: [StartupService, Global] //StartupService, GlobalClass are Required for the WebProjects Module to Work.
})
export class WebProjectsModule {}
网页.component.ts
//Webpage Component is the First Component to be loaded Under the Webprojects Module.
import { Component, ViewChild, OnInit } from '@angular/core';
import { Global } from '../../../../class.global'; //Global Class Contains the Global Variables & Functions Being Used Throughout the Project.
import { Error } from '../../../../services/shared/error' //Error Class is Used to Display Errors
import { StartupService } from '../../../../services/shared/startup.service'; //StartupService is Required to Load the Project, Page, Object & Elements.
import { Project } from '../../../../services/projects/webprojects/project'; //Project Model is Required to Constrain the Type of Data Being Received from the Startup Service getProjects().
import { Projectpage } from '../../../../services/projects/webprojects/projectpage'; //Project Page Model is Required to Constrain the Type of Data Being Received from the Startup Service getProjectPage().
import { Pageobject } from '../../../../services/projects/webprojects/pageobject'; //Page Object Model is Required to Constrain the Type of Data Being Received from the Statup Service getPageObjects().
import { Property } from '../../../../services/projects/webprojects/property'; //Property Object Model is Required to Constrain the Type of Property Array Being Created for Objects & Elements.
import { SEOService } from '../../../../services/shared/seo.service'; //SEO Service is Used to Display the Page Title, Description, Other SEO Related Content on the Page.
import { ComponentLoaderDirective } from '../../../../services/shared/component-loader.directive';
import { NavbarComponent } from '../objects/navbar/navbar.component';
@Component({
selector: 'app-webpage',
templateUrl: './webpage.component.html',
styleUrls: ['./webpage.component.scss']
})
export class WebpageComponent implements OnInit {
@ViewChild(ComponentLoaderDirective, {static: true}) pageObjectLoader!: ComponentLoaderDirective;
responseProject: Project[] = []; //Variable of Type Project Array Used to Store the Array of Projects Received from the Startup Service getProjects().
project: any = {}; //Variable of Type Any Used to Store the Parameters of the Current Project being Loaded. Initializing with Empty Object.
projectId: number = 0; //Variable of Type Number Used to Store the Id of the Current Project being Loaded. Initilizing with 0.
projectType: string = 'web'; //Variable of Type String Used to Store the Type of the Current Project being Loaded. Initializing with web.
responseProjectPage: Projectpage[] = []; //Variable of Type Projectpage Array Used to Store the Object of Projectpage Received from the Statup Service getProjectPage().
projectPage: any = {}; //Aggregate of Type Object Used to Store the Parameters of Project Page, Project & Page. Initializing with Empty Object.
projectPageProperties: Property[] = []; //Variable of Type Property[] Used to Store Array of Properties of Project Page.
page: any = {}; //Variable of Type Any Used to Store the Parameters of the Current Page being Loaded.
pageTitle: string = ''; //Variable of Type String Used to Store the Title of the Current Page being Loaded.
pageDescription: string = ''; //Variable of Type String Used to Store the Description of the Current Page being Loaded.
pageProperties: Property[] = []; //Variable of Type Property Used to Store the Properties of the Page being Loaded.
pageType: string = 'home'; //Variable of Type String Used to Store the Type of Current Page being Loaded. Initializing with home by default to be loaded. Unless Overwritten by the Route.
pageObjects: Pageobject[] = []; //Variable of Type Any Used to Store the Page & Object Parameters Relevant to the Page Being Loaded. Initializing with Empty Object.
pageObjectProperties: Property[] = []; //Variable of Type Property[] Used to Store the Array of Page Object Properties.
object: any = {}; //Variable of Type Any Used to Store the Object Relevant to the Page Being Loaded. Initializing with Empty Object.
objectProperties: Property[] = []; //Variable of Type Property[] Used to Store the Array of Object Properties.
properties: Property[] = []; //Variable of Type Property[] Used to Store Array of Properties.
active: boolean = true; //Initializing with true. All the Requests to Get the Projects, ProjectPages & PageObjects are with Active = true.
global = new Global();
error = new Error();
constructor(private startupService: StartupService, private seoService: SEOService) {};
async ngOnInit(){
try{
this.responseProject = await this.startupService.getProjects(this.projectType,this.active).toPromise();
var i = this.responseProject.length;
while(i--){
if(this.responseProject[i].tags.indexOf(window.location.href) == -1){ //Using window.location.href to Get the Url Which Was Loaded & Get the Project Accordingly.
this.responseProject.splice(i, 1); //Removes the Project from the Array if it is Not Relevant to the Current Project.
}
};
if(this.responseProject.length > 0){ //Checks if Atleast 1 Project is Received.
this.project = this.responseProject[0]; //Storing the Relevant Project in the Project Variable
this.projectId = this.project.nid; //Storing the Relevant Project Id in the projectId Variable.
this.responseProjectPage = await this.startupService.getProjectPage(this.projectId, this.pageType, this.active).toPromise();
//Use the getPage() in StartupService to Get the Home Page of the Relevant Project Being Loaded.
if(Object.keys(this.responseProjectPage).length === 1){ //Checks if the Array Received is Not Empty.
this.projectPage = this.responseProjectPage[0]; //Aggregate Object Received from the Database is Stored in projectPage Variable.
this.projectPageProperties = this.projectPage.properties; //Project Page Properties which are a Part of the Aggregate Received is Separately Stored in projectPageProperties Variable.
this.page = this.projectPage.page; //Page Object which is Part of the Aggregate Received is Separately Stored in page Variable.
this.pageProperties = this.page.properties; //Page Properties which are a Part of the Page Object Received are Separately Stored in pageProperties Variable.
//We Pick All the Properties from projectPageProperties & the Remaining Properties from pageProperties which are Not a Part of projectPageProperties.
var namesToFilter = new Set(this.projectPageProperties.map(d => d.name)); //We Get All the Names in the projectPageProperties Array and Store them in namesToFilter Array.
this.properties = [...this.projectPageProperties, ...this.pageProperties.filter(d => !namesToFilter.has(d.name))]; //We Merge Both the Arrays and Skip the Objects with Names in the namesToFilter Array.
//Looping through the Properties Array to Get the Page Title & Description for the <head> Tag.
this.properties.forEach((property: Property) => {
this.pageTitle = (property.name === 'pgTitle')?property.value:this.pageTitle;
this.pageDescription = (property.name === 'pgDescription')?property.value:this.pageDescription;
});
this.seoService.updateTitle(this.pageTitle); //Using the SEO Service, We Update the <html><head><title> Tag of the Page.
this.seoService.updateDescription(this.pageDescription); //Using the SEO SErvice, We Update the <html><head><meta = "description"> Tag is the Page.
this.pageObjects = this.projectPage.pageobjects; //Storing the Page Objects Array in pageObjects Variable.
if(this.pageObjects.length > 0){ //Checking if there is Atleast One Page Object.
const viewContainerRef = this.pageObjectLoader.viewContainerRef; //We Use Instance of Component Loader Directive to Define Where to Load the Child Component.
this.pageObjects.forEach((pageObject: Pageobject) => { //Looping through the Page Objects.
this.pageObjectProperties = pageObject.properties; //Storing the Page Object Properties Array in pageObjectProperties Variable.
this.object = pageObject.object; //Storing the Object which is Part of Page Object in the object Variable.
this.objectProperties = this.object.properties; //Storing the Properties of Object in the objectProperties Variable.
//We Pick All the Properties from pageObjectProperties & the Remaining Properties from objectProperties which are Not a Part of pageObjectProperties.
namesToFilter = new Set(this.pageObjectProperties.map(d => d.name)); //We Get All the Names in the pageObjectProperties Array and Store them in namesToFilter Array.
this.properties = [...this.pageObjectProperties, ...this.objectProperties.filter(d => !namesToFilter.has(d.name))]; //We Merge Both the Arrays and Skip the Objects with Names in the namesToFilter Array.
switch(this.object.path){ //Based on the Path of Object We Load the Respective Component.
case 'NavbarComponent':{ //NavbarComponent Relates with the Object Type of navbar.
const componentRef = viewContainerRef.createComponent<any>(NavbarComponent);
componentRef.instance.properties = this.properties;
break;
}
};
});
} else { //Throw Error if No Page Objects Were Received.
this.error.display('Error Loading Project in webpage.component. Unable to Fetch Page Objects Data...');
};
} else { //Throw Error if Query Ran Succcessfully. However, No Project Page Was Received.
this.error.display('Error Loading Project in webpage.component. Unable to Fetch Project Page Data...');
};
} else { //Throw Error if Query Ran Succcessfully. However, No Projects Were Received.
this.error.display('Error Loading Project in webpage.component. Unable to Fetch Projects Data...');
};
} catch(error){
this.error.display('Error Loading Project in webpage.component...', error);
};
};
};
网页.component.html
<ng-template pageObjectLoader></ng-template>
<div>Webpage Works!</div>
objects.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { NavbarComponent } from './navbar/navbar.component';
import { ComponentLoaderDirective } from '../../../../services/shared/component-loader.directive';
import { MaterialModule } from '../material/material.module';
let components = [NavbarComponent, ComponentLoaderDirective];
@NgModule({
declarations: [components],
imports: [CommonModule, MaterialModule],
exports: [components]
})
export class ObjectsModule {}
navbar.component.ts
import { Component, OnInit, Input } from '@angular/core';
import { Property } from '../../../../../services/projects/webprojects/property';
@Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.scss']
})
export class NavbarComponent implements OnInit {
@Input() properties: Property[] = []; //Properties of Navbar Component
@Input() elements: any; //Elements of Navbar Component
class: string = '';
ngOnInit(): void {
this.properties.forEach((property) => {
this.class += (property.type = 'class')?(this.class == '')?property.value:' ' + property.value:'';
});
};
}
navbar.component.html
<mat-toolbar [ngClass]="class">
<span>Yellow Pages & Classifieds | ypandc.com</span>
</mat-toolbar>
请阅读 ngmodule-vs-jsmodule 文章,它解释了 jsModules 和 ngModules 之间的区别。它们是两个不同的东西:
JavaScript 模块和 NgModules 可以帮助您模块化代码,但它们有很大不同。 Angular 应用程序依赖于这两种模块。
ngModule 有一个“import”属性,可以导入其他模块,这些模块的导出类是此 NgModule 中声明的组件模板所需要的。
jsModule 应该声明语法,以便在另一个 .ts 文件中使用 js 模块。
导出/导入 ngModule 属性是必要的,以便声明哪些类可以在其他模块中导入,而 component.ts 中的第二个“导入”只是用于访问文件中对象的打字稿语法。
根据我对模块如何工作的理解,您还需要导出 NavbarComponent 才能在使用 ObjectsModule
的组件中访问它import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { NavbarComponent } from './navbar/navbar.component';
import { ComponentLoaderDirective } from '../../../../services/shared/component-loader.directive';
import { MaterialModule } from '../material/material.module';
let components = [NavbarComponent, ComponentLoaderDirective];
@NgModule({
declarations: [components],
imports: [ CommonModule, MaterialModule ],
exports: [ components, NavbarComponent ]
})
export class ObjectsModule {}
这很简单,不用担心。您需要使用SCAM(单组件角度模块)。下面是一个适合您的示例:
创建您的模块,仅导出一个组件! - 这非常重要
@NgModule({
declarations: [ModuleAComponent],
exports: [ModuleAComponent],
imports: [
ButtonModule // etc
],
})
export class ModuleA {}
在 ModuleB 中导入 ModuleA - 看,很简单
@NgModule({
declarations: [ModuleBComponent],
exports: [ModuleBComponent],
imports: [
ModuleB
],
})
export class ModuleB {}