1. 程式人生 > >基於ng-zorro的ASP.NET ZERO前端實現之程式碼生成器

基於ng-zorro的ASP.NET ZERO前端實現之程式碼生成器

上一篇介紹了整合ng-zorro的過程,本篇我們來看下如何用abp官方的生成器來生成前端程式碼。

Abp官方提供了一個強大的程式碼生成器 ASP.NET Zero Power Tools,它的Visual Studio 外掛在這裡。當然你也可以不用外掛,但你得自己建立json檔案。相關官方文件見這裡

工作原理

生成器(vs外掛)首先根據使用者填寫的Entity相關的內容建立一個json描述檔案,然後開始將真正的程式碼生成核心程式釋放到aspnet-core\AspNetZeroRadTool這個目錄下,然後開始執行生成,命令列:dotnet AspNetZeroRadTool.dll YourEntity.Json

。執行過程中會掃描FileTemplatesn內的檔案進行實際的檔案替換等操作生成最終程式碼檔案。

AspNetZeroRadTool資料夾

除了config.json其餘內容均可以從生成器(vs外掛)自動釋放出來。所以你如果用git其實可以把除config.json外的檔案ignore。

FileTemplates 資料夾

FileTemplates資料夾顧名思義是放了一些模板檔案。本次我們只關注Angular模板,目錄結構如下:

  • ComponentHtmlTemplate:用於生成 Asp.net Zero 5.4之前的component html
  • ComponentTemplate:用於生成component ts
  • ComponentTurboTableHtmlTemplate:用於生成 Asp.net Zero 5.4之後的componnet html (由於5.4之後Table更換成了TurboTable元件)
  • CreateOrEditComponentHtmlTemplate:用於生成建立或修改對話方塊的html
  • CreateOrEditComponentTemplate:用於生成建立或修改對話方塊的ts
  • LookupTables:用於生成選擇關聯實體對話方塊的html/ts (如果你定義的實體有外來鍵關聯,在編輯或建立時會通過該對話方塊進行選擇)
  • ViewEntityComponentHtmlTemplate:用於生成view only對話方塊html (外掛介面中有可選項)
  • ViewEntityComponentTemplate:用於生成view only對話方塊ts (外掛介面中有可選項)

每一個模板資料夾都包含以下三個檔案,我們來看一下:

  • MainTemplate.txt:根據所在資料夾的不同有不同內容(html/ts),其中會有一些佔位的字串,它們以大括號{{...}}包裹。在生成階段會被替換。有幾個比較通用的佔位字串:
    {{Entity_Name_Here}}表示首字母大寫的實體名稱,如Book;
    {{entity_Name_Here}}表示首字母小寫的實體名稱,如book。
  • PartialTemplates.txt:MainTemplate.txt中會有一些佔位字串的內容會根據條件從這個檔案中獲取。比如生成器在處理MainTemplate.txt時遇到{{Get_Excel_Method_Here}}這個佔位符時會去PartialTemplates.txt檔案裡找到對應的內容,然後根據PartialTemplates的內容(有條件的)去填充MainTemplate.txt的內容。
  • TemplateInfo.txt:這個檔案很簡單,裡面只有path和condition。path代表最終生成之後檔案的位置;condition代表是否需要按照本目錄的模板生成程式碼。

建立我們自己的模板

瞭解了以上結構之後,我們來建立我們的模板檔案。

首先我們來禁用一些我們用不到的模板目錄,禁用方式很簡單,在目錄中我們只要複製相應的TemplateInfo.txt檔案並重命名為TemplateInfo.custom.txt,然後修改裡面的condition為"condition":"false"即可。我們需要禁用ComponentTurboTableHtmlTemplateLookupTables\LookupTableComponentTurboTableHtmlTemplateLookupTables\LookupTableCssTemplate這幾個資料夾。

以下我們建立一個列表顯示頁的html模板頁:

  1. 建立模板目錄ComponentNgZorroTableHtmlTemplate
  2. 建立模板三個檔案MainTemplate.txt、PartialTemplates.txt、TemplateInfo.txt

MainTemplate.txt的內容:

<page-header [title]="title">
    <ng-template #title>
        {{l("{{Entity_Name_Plural_Here}}")}}
        <span class="text-sm text-grey-dark">
            <nz-divider nzType="vertical"></nz-divider>
            {{l("{{Entity_Name_Plural_Here}}HeaderInfo")}}
        </span>
    </ng-template>
</page-header>
<nz-card [nzBordered]="false">
    <form nz-form [nzLayout]="'inline'" class="search__form">
        <nz-row nzGutter="8">
            <nz-col nzSm="24">
                <nz-form-item>
                    <nz-form-control>
                        <nz-input-group nzSearch [nzSuffix]="suffixSearchButton">
                            <input type="text" nz-input [(ngModel)]="filterText" name="filterText" [placeholder]="l('SearchWithThreeDot')">
                            <ng-template #suffixSearchButton>
                                <button nz-button nzType="primary" nzSearch (click)="refresh($event)">
                                    <i class="anticon anticon-search"></i>
                                </button>
                            </ng-template>
                        </nz-input-group>
                    </nz-form-control>
                </nz-form-item>
            </nz-col>
        </nz-row>
        <nz-row nzGutter="8" *ngIf="advancedFiltersVisible">
            {{Property_Filter_Template_Here}}{{NP_Filter_Template_Here}}
        </nz-row>
    </form>
    <nz-row nzGutter="8">
        <nz-col nzMd="20" nzSm="12">
            <button nz-button [nzType]="'primary'" *ngIf="isGranted('{{Permission_Value_Here}}.Create')" (click)="createOrEdit()">
                <i class="anticon anticon-plus"></i>
                <span>
                    {{l("CreateNew{{Entity_Name_Here}}")}}
                </span>
            </button>
            <ng-container *ngIf="selectedDataItems.length > 0">
                <button nz-button [nzType]="'danger'" *ngIf="isGranted('{{Permission_Value_Here}}.Delete')" (click)="batchDelete()">
                    <i class="anticon anticon-delete"></i>
                    <span>
                        Delete Selected
                    </span>
                </button>
            </ng-container>
            {{Get_Excel_Button_Here}}            
        </nz-col>
        <nz-col nzMd="4" nzSm="12" class="text-right">
            <a (click)="advancedFiltersVisible=!advancedFiltersVisible">
                {{advancedFiltersVisible ? l('HideAdvancedFilters') : l('ShowAdvancedFilters')}}
                <i class="anticon" [class.anticon-down]="!advancedFiltersVisible" [class.anticon-up]="advancedFiltersVisible"></i>
            </a>
        </nz-col>
    </nz-row>
    <div class="my-md">
        <nz-alert [nzType]="'info'" [nzShowIcon]="true" [nzMessage]="message">
            <ng-template #message>
                <span>
                    <strong class="text-primary">{{selectedDataItems.length}}</strong> items selected
                </span>
                <a (click)="restCheckStatus(dataList)" class="ml-md" *ngIf="selectedDataItems.length>0">
                    {{l('Clear')}}
                </a>
                <nz-divider nzType="vertical"></nz-divider>
                <a (click)="refresh()">
                    {{l('Refresh')}}
                </a>
            </ng-template>
        </nz-alert>
    </div>
    <nz-row class="my-md">
        <nz-table #ajaxTable [nzData]="dataList" [nzTotal]="totalItems" [(nzPageIndex)]="pageNumber" [(nzPageSize)]="pageSize"
            [nzLoading]="isTableLoading" (nzPageIndexChange)="pageNumberChange()" (nzPageSizeChange)="refresh()"
            [nzShowSizeChanger]="true" [nzShowQuickJumper]="true" [nzNoResult]="noDataTemplate" [nzShowTotal]="totalTemplate"
            [nzFrontPagination]="false" [nzScroll]="{x: 'auto'}">
            <ng-template #noDataTemplate>
                <no-data></no-data>
            </ng-template>
            <ng-template #totalTemplate let-total>
                {{l('TotalRecordsCount', total)}}
            </ng-template>
            <thead (nzSortChange)="gridSort($event)">
                <tr>
                    <th nzShowCheckbox [(nzChecked)]="allChecked" [nzDisabled]="allCheckboxDisabled" [nzIndeterminate]="checkboxIndeterminate"
                        (nzCheckedChange)="checkAll($event)" nzWidth="60px"></th>
                    {{NP_Looped_Header_Template_Here}}{{Property_Looped_Header_Template_Here}}
                    <th class="text-center" [hidden]="!isGrantedAny('{{Permission_Value_Here}}.Edit', '{{Permission_Value_Here}}.Delete')">
                        <span>{{l('Actions')}}</span>
                    </th>
                </tr>
            </thead>
            <tbody>
                <tr *ngFor="let item of ajaxTable.data">
                    <td nzShowCheckbox [(nzChecked)]="item.checked" (nzCheckedChange)="refreshCheckStatus(dataList)"></td>
                    {{NP_Looped_Template_Here}}{{Property_Looped_Template_Here}}                    
                    <td>
                        {{View_Button_Here}}
                        <ng-container *ngIf="isGranted('{{Permission_Value_Here}}.Edit')">
                            <a (click)="createOrEdit(item.{{entity_Name_Here}}.id)">
                                <i nz-icon type="edit"></i>
                                {{l('Edit')}}
                            </a>
                            <nz-divider nzType="vertical"></nz-divider>
                        </ng-container>
                        <ng-container *ngIf="isGranted('{{Permission_Value_Here}}.Delete')">
                            <nz-popconfirm [nzTitle]="l('{{Entity_Name_Here}}DeleteWarningMessage', '')" (nzOnConfirm)="delete{{Entity_Name_Here}}(item.{{entity_Name_Here}})"
                                [nzOkText]="l('Ok')" [nzCancelText]="l('Cancel')">
                                <a nz-popconfirm>
                                    <i nz-icon type="delete"></i>
                                    {{l('Delete')}}
                                </a>
                            </nz-popconfirm>
                        </ng-container>
                    </td>
                </tr>
            </tbody>
        </nz-table>
    </nz-row>
</nz-card>

PartialTemplates.txt的內容:

{
"propertyTemplates":[
        {
            "placeholder" : "{{Property_Looped_Header_Template_Here}}",
            "condition" : "{{Property_Listed_Here}} == true",
            "templates" : [
                    {
                    "type" : "default",
                    "content" : "
                            <th nzShowSort nzSortKey=\"{{entity_Name_Here}}.{{property_Name_Here}}\">
                                {{l('{{Property_Name_Here}}')}}
                            </th>
                        "
                    }
                ]
        },
        {
            "placeholder" : "{{Property_Looped_Template_Here}}",
            "condition" : "{{Property_Listed_Here}} == true",
            "templates" : [
                    {
                    "type" : "enum",
                    "content" : "
                    <td>
                        {{l('Enum_{{Property_Type_Here}}' + {{property_Type_Here}}[item.{{entity_Name_Here}}.{{property_Name_Here}}])}}
                    </td>"
                    },
                    {
                    "type" : "bool",
                    "content" : "
                        <td class=\"text-center\">
                            <span class=\"badge badge-success\" *ngIf=\"item.{{entity_Name_Here}}.{{property_Name_Here}}\">{{l('Yes')}}</span>
                            <span class=\"badge badge-error\" *ngIf=\"!item.{{entity_Name_Here}}.{{property_Name_Here}}\">{{l('No')}}</span>
                        </td>"
                    },
                    {
                    "type" : "DateTime",
                    "content" : "
                        <td class=\"text-center\">
                            {{item.{{entity_Name_Here}}.{{property_Name_Here}} | momentFormat:\'L\'}}
                        </td>"
                    },
                    {
                    "type" : "default",
                    "content" : "
                        <td>
                            {{item.{{entity_Name_Here}}.{{property_Name_Here}}}}
                        </td>"
                    }
                ]
        },
        {
            "placeholder" : "{{Property_Filter_Template_Here}}",
            "condition" : "{{Property_Advanced_Filter_Here}} == true",
            "templates" : [
                    {
                    "type" : "enum",
                    "content" : "
                            <nz-col nzSm=\"6\">
                                <nz-form-item>
                                    <nz-form-label for=\"{{Property_Name_Here}}FilterSelect\">
                                        {{l(\"{{Property_Name_Here}}\")}}
                                    </nz-form-label>
                                    <nz-form-control>
                                        <nz-select [(ngModel)]=\"{{property_Name_Here}}Filter\" name=\"{{Property_Name_Here}}Filter\" id=\"{{Property_Name_Here}}FilterSelect\" nzAllowClear>
                                        <nz-option [nzLabel]=\"l('All')\" nzValue=\"-1\"></nz-option>
                                        {{Enum_Option_Looped_Template_Here}}
                                    </nz-select>
                                    </nz-form-control>
                                </nz-form-item>
                            </nz-col>"
                    },
                    {
                    "type" : "bool",
                    "content" : "
                            <nz-col nzSm=\"6\">
                                <nz-form-item>
                                    <nz-form-label for=\"{{Property_Name_Here}}FilterSelect\">
                                        {{l(\"{{Property_Name_Here}}\")}}
                                    </nz-form-label>
                                    <nz-form-control>
                                        <nz-select [(ngModel)]=\"{{property_Name_Here}}Filter\" name=\"{{Property_Name_Here}}Filter\" id=\"{{Property_Name_Here}}FilterSelect\" nzAllowClear>
                                        <nz-option [nzLabel]=\"l('All')\" nzValue=\"-1\"></nz-option>
                                        <nz-option [nzLabel]=\"l('False')\" nzValue=\"0\"></nz-option>
                                        <nz-option [nzLabel]=\"l('True')\" nzValue=\"1\"></nz-option>
                                    </nz-select>
                                    </nz-form-control>
                                </nz-form-item>
                            </nz-col>"
                    },
                    {
                    "type" : "DateTime",
                    "content" : "
                            <nz-col nzSm=\"6\">
                                <nz-form-item>
                                    <nz-form-label nzFor=\"{{Property_Name_Here}}Filter\">
                                        {{l(\"{{Property_Name_Here}}\")}}
                                    </nz-form-label>
                                    <nz-form-control>
                                        <range-picker name=\"{{property_Name_Here}}Filter\" id=\"{{Property_Name_Here}}Filter\" [(ngModel)]=\"min{{Property_Name_Here}}Filter\" [(ngModelEnd)]=\"max{{Property_Name_Here}}Filter\"
                                            [nzPlaceHolder]=\"[l('StartDateTime'),l('EndDateTime')]\"></range-picker>
                                    </nz-form-control>
                                </nz-form-item>
                            </nz-col>"
                    },
                    {
                    "type" : "numeric",
                    "content" : "
                            <nz-col nzSm=\"6\">
                                <nz-form-item>
                                    <nz-form-label nzFor=\"Min{{Property_Name_Here}}Filter\">
                                        {{l(\"{{Property_Name_Here}}\")}}
                                    </nz-form-label>
                                    <nz-form-control>
                                        <nz-input-number id=\"Min{{Property_Name_Here}}Filter\" name=\"min{{Property_Name_Here}}Filter\" [(ngModel)]=\"min{{Property_Name_Here}}Filter\" [nzPlaceHolder]=\"{{l('MinValue')}}\"></nz-input-number>
                                        <nz-input-number id=\"Max{{Property_Name_Here}}Filter\" name=\"max{{Property_Name_Here}}Filter\" [(ngModel)]=\"max{{Property_Name_Here}}Filter\" [nzPlaceHolder]=\"{{l('MaxValue')}}\"></nz-input-number>
                                    </nz-form-control>
                                </nz-form-item>
                            </nz-col>"
                    },
                    {
                    "type" : "default",
                    "content" : "
                            <nz-col nzSm=\"6\">
                                <nz-form-item>
                                    <nz-form-label nzFor=\"{{Property_Name_Here}}Filter\">
                                        {{l(\"{{Property_Name_Here}}\")}}
                                    </nz-form-label>
                                    <nz-form-control>
                                        <input nz-input id=\"{{Property_Name_Here}}Filter\" name=\"{{property_Name_Here}}Filter\" [(ngModel)]=\"{{property_Name_Here}}Filter\">
                                    </nz-form-control>
                                </nz-form-item>
                            </nz-col>"
                    }
                ]
        }
    ],
"navigationPropertyTemplates":[
    {
            "placeholder" : "{{NP_Looped_Header_Template_Here}}",
            "templates" : [
                    {
                    "relation" : "single",
                    "content" : "
                                <th nzShowSort nzSortKey=\"{{nP_Foreign_Entity_Name_Here}}{{NP_Display_Property_Name_Here}}{{NP_Duplication_Number_Here}}\">
                                    {{l('{{NP_Display_Property_Name_Here}}')}}
                                </th>
                            "
                    }
                ]
        },
        {
            "placeholder" : "{{NP_Looped_Template_Here}}",
            "templates" : [
                    {
                    "relation" : "single",
                    "content" : "
                    <td>
                        {{item.{{nP_Foreign_Entity_Name_Here}}{{NP_Display_Property_Name_Here}}{{NP_Duplication_Number_Here}}}}
                    </td>"
                    }
                ]
        },
        {
            "placeholder" : "{{NP_Filter_Template_Here}}",
            "templates" : [
                    {
                    "relation" : "single",
                    "content" : "
                            <nz-col nzSm=\"6\">
                                <nz-form-item>
                                    <nz-form-label nzFor=\"{{NP_Foreign_Entity_Name_Here}}{{NP_Display_Property_Name_Here}}{{NP_Duplication_Number_Here}}Filter\">
                                        ({{l(\"{{NP_Foreign_Entity_Name_Here}}{{NP_Duplication_Number_Here}}\")}}) {{l(\"{{NP_Display_Property_Name_Here}}\")}}
                                    </nz-form-label>
                                    <nz-form-control>
                                        <input nz-input id=\"{{NP_Foreign_Entity_Name_Here}}{{NP_Display_Property_Name_Here}}{{NP_Duplication_Number_Here}}Filter\" name=\"{{nP_Foreign_Entity_Name_Here}}{{NP_Display_Property_Name_Here}}{{NP_Duplication_Number_Here}}Filter\" [(ngModel)]=\"{{nP_Foreign_Entity_Name_Here}}{{NP_Display_Property_Name_Here}}{{NP_Duplication_Number_Here}}Filter\">
                                    </nz-form-control>
                                </nz-form-item>
                            </nz-col>"
                    }
                ]
        }
    ],
"enumTemplates":[
        {
            "placeholder" : "{{Enum_Option_Looped_Template_Here}}",
            "content" : "
            <nz-option [nzLabel]=\"l('Enum_{{Enum_Name_Here}}_{{Enum_Property_Value_Here}}')\" nzValue=\"{{Enum_Property_Value_Here}}\"></nz-option>"
        }
    ],
"conditionalTemplates":[
        {
            "placeholder": "{{View_Button_Here}}",
            "condition": "{{Create_View_Only_Here}} == true",
            "content": "
                    <ng-container>
                            <a (click)=\"view{{Entity_Name_Here}}(item.id)\">
                                <i nz-icon type=\"search\"></i>
                                {{l('View')}}
                            </a>
                            <nz-divider nzType=\"vertical\"></nz-divider>
                        </ng-container>"
        },
        {
            "placeholder": "{{Get_Excel_Button_Here}}",
            "condition": "{{Create_Excel_Export_Here}} == true",
            "content": "<button nz-button nzType=\"default\" (click)=\"exportToExcel()\"><i nz-icon type=\"file-excel\"></i><span>{{l('ExportToExcel')}}</span></button>"
        }
    ]
}

TemplateInfo.txt的內容:

{
    "path" : "app\\{{menu_Position_Here}}\\{{namespace_Relative_Here}}\\{{entity_Name_Plural_Here}}\\{{entity_Name_Plural_Here}}.component.html",
    "condition": "true"
}

建立列表顯示的typescript檔案:
ts模板目錄我們直接使用已有的模板目錄ComponentTemplate, 這裡需要注意如需要修改預設的模板檔案內容,必須複製該檔案並重命名成.custom.txt。比如複製MainTemplate.txt為MainTemplate.custom.txt,之後在MainTemplate.custom.txt新增你自己的模板內容。
修改後的MainTemplate.custom.txt內容:

import { Component, Injector } from '@angular/core';
import { {{Entity_Name_Plural_Here}}ServiceProxy, {{Entity_Name_Here}}Dto {{Enum_Import_Here}}, Get{{Entity_Name_Here}}ForView } from '@shared/service-proxies/service-proxies';
import { PagedListingComponentBase, PagedRequestDto } from '@shared/common/paged-listing-component-base';
import { CreateOrEdit{{Entity_Name_Here}}ModalComponent } from './create-or-edit-{{entity_Name_Here}}-modal.component';{{View_Component_Import_Here}}
{{View_Component_Import_Here}}
import { FileDownloadService } from '@shared/utils/file-download.service';

import { finalize } from 'rxjs/operators';
import * as moment from 'moment';
import * as _ from 'lodash';

@Component({
    templateUrl: './{{entity_Name_Plural_Here}}.component.html'
})
export class {{Entity_Name_Plural_Here}}Component extends PagedListingComponentBase<Get{{Entity_Name_Here}}ForView> {

    advancedFiltersAreShown = false;
    filterText = '';
{{Property_Filter_Def_Here}}{{NP_Filter_Def_Here}}
    {{enum_Def_Here}}

    constructor(
        injector: Injector,
        private _{{entity_Name_Plural_Here}}ServiceProxy: {{Entity_Name_Plural_Here}}ServiceProxy,
        private _fileDownloadService: FileDownloadService
    ) {
        super(injector);
    }

    protected fetchDataList(request: PagedRequestDto, pageNumber: number, finishedCallback: () => void): void {
        this._{{entity_Name_Plural_Here}}ServiceProxy
            .getAll(
                this.filterText,{{Property_Filter_Param_Here}}{{NP_Filter_Param_Here}}
                request.sorting,
                request.skipCount,                
                request.maxResultCount
            )
            .pipe(finalize(finishedCallback))
            .subscribe(result => {
                this.dataList = result.items;
                this.showPaging(result);
            });
    }

    createOrEdit(id?: number): void {
        this.modalHelper
            .createStatic(CreateOrEdit{{Entity_Name_Here}}ModalComponent, { {{entity_Name_Here}}Id: id }, { size: 'md' })
            .subscribe(res => {
                if (res) {
                    this.refresh();
                }
            });
    }

    delete{{Entity_Name_Here}}({{entity_Name_Here}}: {{Entity_Name_Here}}Dto): void {
        this._{{entity_Name_Plural_Here}}ServiceProxy.delete({{entity_Name_Here}}.id)
            .subscribe(() => {
                this.refresh();
                this.notify.success(this.l('SuccessfullyDeleted'));
            });
    }

    {{Get_View_Component_Method_Here}}
    {{Get_Excel_Method_Here}}
}

PartialTemplates.custom.txt內容:

{
"propertyTemplates":[
        {
            "placeholder" : "{{Property_Filter_Def_Here}}",
            "condition" : "{{Property_Advanced_Filter_Here}} == true",
            "templates" : [
                    {
                    "type" : "enum",
                    "content" : "       {{property_Name_Here}}Filter = -1;
"
                    },
                    {
                    "type" : "byte",
                    "content" : "       max{{Property_Name_Here}}Filter : string = '';
        min{{Property_Name_Here}}Filter : string = '';
"
                    },
                    {
                    "type" : "numeric",
                    "content" : "       max{{Property_Name_Here}}Filter : number;
        max{{Property_Name_Here}}FilterEmpty : number;
        min{{Property_Name_Here}}Filter : number;
        min{{Property_Name_Here}}FilterEmpty : number;
"
                    },
                    {
                    "type" : "DateTime",
                    "content" : "       max{{Property_Name_Here}}Filter : moment.Moment;
        min{{Property_Name_Here}}Filter : moment.Moment;
"
                    },
                    {
                    "type" : "bool",
                    "content" : "       {{property_Name_Here}}Filter = -1;
"
                    },
                    {
                    "type" : "default",
                    "content" : "       {{property_Name_Here}}Filter = '';
"
                    }
                ]
        },
        {
            "placeholder" : "{{Property_Filter_Param_Here}}",
            "condition" : "{{Property_Advanced_Filter_Here}} == true",
            "templates" : [
                    {
                    "type" : "byte",
                    "content" : "
            this.max{{Property_Name_Here}}Filter == null ? '' : this.max{{Property_Name_Here}}Filter,
            this.min{{Property_Name_Here}}Filter == null ? '' : this.min{{Property_Name_Here}}Filter,"
                    },
                    {
                    "type" : "numeric",
                    "content" : "
            this.max{{Property_Name_Here}}Filter == null ? this.max{{Property_Name_Here}}FilterEmpty: this.max{{Property_Name_Here}}Filter,
            this.min{{Property_Name_Here}}Filter == null ? this.min{{Property_Name_Here}}FilterEmpty: this.min{{Property_Name_Here}}Filter,"
                    },
                    {
                    "type" : "DateTime",
                    "content" : "
            this.max{{Property_Name_Here}}Filter,
            this.min{{Property_Name_Here}}Filter,"
                    },
                    {
                    "type" : "default",
                    "content" : "
            this.{{property_Name_Here}}Filter,"
                    }
                ]
        }
    ],
"navigationPropertyTemplates":[
        {
            "placeholder" : "{{NP_Filter_Def_Here}}",
            "templates" : [
                    {
                    "relation" : "single",
                    "content" : "       {{nP_Foreign_Entity_Name_Here}}{{NP_Display_Property_Name_Here}}{{NP_Duplication_Number_Here}}Filter = '';
"
                    }
                ]
        },
        {
            "placeholder" : "{{NP_Filter_Param_Here}}",
            "templates" : [
                    {
                    "relation" : "single",
                    "content" : "
            this.{{nP_Foreign_Entity_Name_Here}}{{NP_Display_Property_Name_Here}}{{NP_Duplication_Number_Here}}Filter,"
                    }
                ]
        }
    ],
"enumTemplates":[
        {
            "placeholder" : "{{Enum_Import_Here}}",
            "content" : ", {{Entity_Name_Here}}Dto{{Enum_Used_For_Property_Name_Here}}"
        },
        {
            "placeholder" : "{{enum_Def_Here}}",
            "content" : "{{enum_Name_Here}} = {{Entity_Name_Here}}Dto{{Enum_Used_For_Property_Name_Here}};
        "
        }
    ],
"conditionalTemplates":[
        {
            "placeholder": "{{View_Component_Import_Here}}",
            "condition": "{{Create_View_Only_Here}} == true",
            "content": "
import { View{{Entity_Name_Here}}ModalComponent } from './view-{{entity_Name_Here}}-modal.component';"
        },  
        {
            "placeholder": "{{Get_Excel_Method_Here}}",
            "condition": "{{Create_Excel_Export_Here}} == true",
            "content": "exportToExcel(): void {
        this._{{entity_Name_Plural_Here}}ServiceProxy.get{{Entity_Name_Plural_Here}}ToExcel(
        this.filterText,{{Property_Filter_Param_Here}}{{NP_Filter_Param_Here}}
        )
        .subscribe(result => {
            this._fileDownloadService.downloadTempFile(result);
         });
    }"
        },
        {
            "placeholder": "{{Get_View_Component_Method_Here}}",
            "condition": "{{Create_View_Only_Here}} == true",
            "content": "view{{Entity_Name_Here}}(id): void {
                this.modalHelper
                    .create(View{{Entity_Name_Here}}ModalComponent, {
                        {{entity_Name_Here}}Id: id
                    }, { size: 'md' })
                    .subscribe(() => { });
            }"
        }
    ]
}

按照上述過程修改其他模板目錄中的內容即可使用程式碼生成器按照你的模板進行程式碼生成。

在我的專案裡已經包含了修改好的模板檔案,請自行檢視。

專案地址:https://github.com/rqx110/abp-ng-zorro

覺得還可以,請不要吝嗇你的Star

使用

我們來簡單測試下生成:

這裡注意到幾個帶“Customized”的就是我們將預設模板自定義後的結果。

再來看一個生成後的ts檔案,可以和上面的模板檔案進行對比:

import { Component, Injector } from '@angular/core';
import { BooksServiceProxy, BookDto , GetBookForView } from '@shared/service-proxies/service-proxies';
import { PagedListingComponentBase, PagedRequestDto } from '@shared/common/paged-listing-component-base';
import { CreateOrEditBookModalComponent } from './create-or-edit-book-modal.component';
import { ViewBookModalComponent } from './view-book-modal.component';

import { ViewBookModalComponent } from './view-book-modal.component';
import { FileDownloadService } from '@shared/utils/file-download.service';

import { finalize } from 'rxjs/operators';
import * as moment from 'moment';
import * as _ from 'lodash';

@Component({
    templateUrl: './books.component.html'
})
export class BooksComponent extends PagedListingComponentBase<GetBookForView> {

    advancedFiltersAreShown = false;
    filterText = '';
        nameFilter = '';
        authorFilter = '';

    

    constructor(
        injector: Injector,
        private _booksServiceProxy: BooksServiceProxy,
        private _fileDownloadService: FileDownloadService
    ) {
        super(injector);
    }

    protected fetchDataList(request: PagedRequestDto, pageNumber: number, finishedCallback: () => void): void {
        this._booksServiceProxy
            .getAll(
                this.filterText,
            this.nameFilter,
            this.authorFilter,
                request.sorting,
                request.skipCount,                
                request.maxResultCount
            )
            .pipe(finalize(finishedCallback))
            .subscribe(result => {
                this.dataList = result.items;
                this.showPaging(result);
            });
    }

    createOrEdit(id?: number): void {
        this.modalHelper
            .createStatic(CreateOrEditBookModalComponent, { bookId: id }, { size: 'md' })
            .subscribe(res => {
                if (res) {
                    this.refresh();
                }
            });
    }

    deleteBook(book: BookDto): void {
        this._booksServiceProxy.delete(book.id)
            .subscribe(() => {
                this.refresh();
                this.notify.success(this.l('SuccessfullyDeleted'));
            });
    }

    viewBook(id): void {
                this.modalHelper
                    .create(ViewBookModalComponent, {
                        bookId: id
                    }, { size: 'md' })
                    .subscribe(() => { });
            }
    exportToExcel(): void {
        this._booksServiceProxy.getBooksToExcel(
        this.filterText,
            this.nameFilter,
            this.authorFilter,
        )
        .subscribe(result => {
            this._fileDownloadService.downloadTempFile(result);
         });
    }
}

結束

ASP.NET Zero Power Tools是一個商業產品,你必須購買才能使用。當然你也可以動(po)手(jie)來使用。比如: