Vlad, Dynamic forms, eh? We seem to have a lot in common!
Vlad, If you find an answer to that one let me know.
Hi Vlad, It seems we are on similar paths! Add the settings during initialisation using the instructions above and then allow your tenant to change them by adding an extra tab in tenant-settings.component.html. For example I have three settings, registration code for devices (we have spoken about this privately), and data provider name and api (I allow a tenants to load and save data to a third-party system). To facilitate tenant changes to these values I use the following code:
<tab *ngIf="true" heading="YourCompanyName" customClass="m-tabs__item">
<h5>{{l("Devices")}}</h5>
<div class="form-group">
<label>{{l("RegistrationCode")}}</label>
<input type="text" #registrationCode="ngModel" name="registrationCode" class="form-control" [ngClass]="{'edited':settings.nuage.registrationCode}" [(ngModel)]="settings.nuage.registrationCode"
maxlength="6" minlength="4" pattern="[A-Za-z0-9]+" required>
<div [hidden]="registrationCode.valid || registrationCode.pristine" class="m-form__help m--font-danger">
<div [hidden]="!registrationCode.hasError('required')">{{l("RequiredField", l('RegistrationCode'))}}</div>
<div [hidden]="!registrationCode.hasError('pattern')">{{l("OnlyCharactersAndNumbersAllowed")}}</div>
<div [hidden]="!registrationCode.hasError('minlength') && !registrationCode.hasError('maxlength')">{{l("StringLengthDoesntMatch", l('RegistrationCode'), "4", "6")}}</div>
</div>
</div>
<h5>{{l("DataProviders")}}</h5>
<div class="form-group">
<label>{{l("DataProvider")}}</label>
<input readonly type="text" name="dataProvider" class="form-control" [ngClass]="{'edited':settings.nuage.dataProvider}"
[(ngModel)]="settings.nuage.dataProvider" maxlength="256">
</div>
<div class="form-group">
<label>{{l("DataProviderApiUrl")}}</label>
<input type="text" name="dataProviderApiUrl" class="form-control" [ngClass]="{'edited':settings.nuage.dataProviderApiUrl}"
[(ngModel)]="settings.nuage.dataProviderApiUrl" maxlength="256">
</div>
</tab>
Hope this helps.
@vlad, try this:
{
"version": "0.2.0",
"configurations": [{
"name": "Launch Chrome against localhost",
"type": "chrome",
"request": "launch",
"url": "http://localhost:4200",
"sourceMaps": true,
"webRoot": "${workspaceRoot}",
"sourceMapPathOverrides": {
"webpack:///./*": "${workspaceRoot}/*"
}
}]
}
There are plenty of other examples, the key is to first add the Chrome extension to VSCode.
Yep, I'm one for source code as well. In my case I don't like the Angular templates produced because I am not a fan of using modals for CRUD operations. Call me old school but I like the idea of an index page for a grid (DevExpress, NgPrime or Kendo) with delete functionality and separate pages for create, read and update. Here is my template for the index page:
<div [@routerTransition]>
<div class="m-content">
<app-person-list *ngIf="isList" (notifyEdit)="onEditButtonSelected($event)" (notifyCreate)="onCreateButtonSelected($event)" (notifyView)="onViewButtonSelected($event)"></app-person-list>
<app-create-person *ngIf="isCreate" (notifyCreateSaved)="displayList($event)" (notifyCreateClose)="displayList($event)"></app-create-person>
<app-edit-person *ngIf="isEdit" (notifyEditSaved)="displayList($event)" (notifyEditClose)="displayList($event)" [person]="person"></app-edit-person>
<app-view-person *ngIf="isView" (notifyViewClose)="displayList($event)" [person]="person"></app-view-person>
</div>
</div>
In addition I prefer the Reactive approach for forms instead of the template system used by the RAD tool, not least for in-line error checking. Now, it would be great if I could cut into your code (I presume you're using T4) and produce what I wanted for the client rather than the tedious and error-prone job of deleting, cutting and pasting.... Having said that, it's an awesome tool and at least saves a lot of time in the core. AWESOME JOB BOYS!!!!
@ismcagdas, that's a shame. I was hoping to extend the usage of settings to reduce the number of extensibility points for upgrades. That is to say, my aim is to use existing Zero functionality wherever possible as opposed to extending entities. This means that when it comes to upgrading I can merge my code and make as few changes to the Zero system as possible. This applies both to the core and to angular, in the latter I have created my own module which is lazy loaded.
.Net Core, Angular I have searched source code to no avail to find out usage of the settings definitions:
new SettingDefinition(
name: NuageSettings.NuageTenantManagement.RegistrationCode,
defaultValue: null,
scopes: SettingScopes.Tenant,
displayName: null,
description: null,
group: null,
isVisibleToClients: true,
isInherited: true,
customData: null),
I have carefully read the documentation at https://aspnetboilerplate.com/Pages/Documents/Setting-Management but the following explanation gives me only reason to scratch my head: Name (required): A setting must have a system-wide unique name. It's a good idea to define a const string for a setting name instead of using a magic string. Default value: A setting may have a default value. This value can be null or an empty string. Scopes: A setting should define it's scope (see below). Display name: A localizable string that can be used to show setting's name later in the UI. Description: A localizable string that can be used to show a setting's description later in the UI. Group: Can be used to group settings. This is just for the UI, and not used in setting management. IsVisibleToClients: Set true to make a setting usable on the client-side. isInherited: Used to set if this setting is inherited by tenant and users (See setting scope section). customData: Can be used to set custom data for this setting definition. My question is:
Is there anywhere i can find examples of implementation of these properties, in particular displayName, description, group, isInherited and customData???
@Aaron, another one of life's little mysteries solved, once again I am in debt to your expertise. An excellent piece of code, well done!!!! This alone is worth the upgrade to 5.1.0, I will wait with baited breath for the user interface... Thank you again for your help.
.Net Core, Angular v5.1.0 I love the idea of the new Entity change history functionality offered in 5.1.0 and wanted to test before upgrading my current project. I download and create a new project. I add a new entity using the new RAD tool - GREAT JOB GUYS - and disable the Add migration and Update database options so I can carry out some final modifications before migrating to the database::
[Table("NcPerson")]
[Audited]
public class Person : FullAuditedEntity<Guid>, IMustHaveTenant, IMayHaveOrganizationUnit, IExtendableObject
{
public int TenantId { get; set; }
public long? OrganizationUnitId { get; set; }
[Required]
[StringLength(PersonConsts.MaxSalutationLength, MinimumLength = PersonConsts.MinSalutationLength)]
public virtual string Salutation { get; set; }
public string ExtensionData { get; set; }
}
I then migrate to the database. I modify my CoreModule.PreInitialize() method with the following lines:
Configuration.EntityHistory.IsEnabled = true;
Configuration.EntityHistory.Selectors.Add(
new NamedTypeSelector(
"Abp.FullAuditedEntities",
type => typeof(IFullAudited).IsAssignableFrom(type)
));
I compile and run the project successfully. I add several people and update and delete one person. I have no data in my AbpEntityChangeSets table or associated tables. I started without the [Audited] attribute on my entity and without the line Configuration.EntityHistory.IsEnabled = true; (both of which should be unnecessary according to the documentation at [https://github.com/aspnetboilerplate/aspnetboilerplate/blob/dev/doc/WebSite/Entity-History.md]). What am I doing wrong?
Doh! @brandonmurphy - exactly what I was looking for, I was looking in a previous development database, thanks for casting light on the error of my ways!