Table of Contents
Using the Basic Admin Page Component
- creates a basic grid with editing dialog
- most arguments are pass-throughs for the grid and fieldmapper editor
- the recordLabel input is what gets used on the "New $THING" toolbar button / action menu
- note magic URLs! use them to replace the auto-generated interfaces with your own
- admin/local/ + schema + class = admin/local/config/copy_alert_type
- edit admin/local splash or admin/server splash links as appropriate
- you do not need <eg-fm-editor>! You can use your own, but you will have to create a bunch of scaffolding for opening and closing the editing dialog.
- you will have to create an SQL upgrade file + 950.seed data for your grid settings
Using the Fieldmapper Editor
Input types render automatically based on field data type. Look through fm-editor.component.html
, <ng-container [ngSwitch]="inputType(field)">
for all the variations. A custom template will override these defaults AND the readonly
setting.
To render a combobox, set that field's options to customValues: myComboBoxEntriesArray:
[fieldOptions]="{ myFieldName1: {customValues: myComboBoxEntriesArray} }"
To render a custom template (with optional context arguments), set:
[fieldOptions]="{ myFieldName1: {customTemplate: {template: myTemplateRefHashFor1}}, myFieldName2: {customTemplate: {template: myTemplateRefHashFor2, context: {letVarName: myFieldName2ContextData}}} }"
for example:
[fieldOptions]="{ event: {customTemplate: {template: eventTemplate}}, next_status: {customTemplate: {template: next_statusTemplate, context: {statuses: copyStatuses}}} }" <ng-template #next_statusTemplate let-field="field" let-record="record" let-statuses="statuses"> <fieldset *ngIf="!field.isReadOnly()" [attr.aria-label]="field.label" id="next_status-{{record.id()}}" class="scrollable-menu border rounded my-1 p-2 d-sm-flex flex-column flex-wrap"> ... some inputs here </fieldset> <output *ngIf="field.isReadOnly()" id="next_status-{{record.id()}}"> {{ record[field.name]() }} </output> </ng-template>
Always use:
let-field="field" let-record="record"
Optionally use let-myVarInThisTemplate="MyVarSetInFieldOptionsContext"
Pcrud
Use pcrud.retrieve()
to fetch a row by its primary key:
pcrud.retrieve('aou', 1).then( org => console.log(org.shortname()) );
Use pcrud.search()
to do a full query with a WHERE object (the second argument):
pcrud.search('aou', {id : [1,2,3]}).then( orgs => console.log(orgs.length) );
Use pcrud.search()
with a third argument to add limit, order_by, and fleshing:
pcrud.search('aou', {id : {'!=' : null}}, {limit : 10}).then( orgs => { for (const org of orgs) { console.debug('Org unit:', org.id(), org.shortname()); } } );
- Note that booleans are given as
't
' or'f
' - order_by is an object where the keys are the classnames and the values are strings with the field name, then a space, then the direction (
ASC
orDESC
)
Record notes example:
const where = { record: this.recId, deleted: 'f' }; const orderBy: any = {}; if (sort.length) { // Sort provided by grid. orderBy.bren = sort[0].name + ' ' + sort[0].dir; } else { orderBy.bren = 'edit_date'; } const searchOps = { offset: pager.offset, limit: pager.limit, order_by: orderBy, flesh: 2, flesh_fields: {bren: ['creator', 'editor']} }; return this.pcrud.search('bren', where, searchOps) .pipe(tap({ complete: this.emitNoteCount }));
Fleshing
flesh_fields
is an object where the keys are the classnames and the values are arrays of field names. flesh
is the recursion depth.
Note that only pcrud is capable of fleshing; cstore is not. This means org unit settings cannot be fleshed! If you need to turn a user or OU ID into a name from settings data, you will need to add some logic to fetch those separately.
IDL vs. Hash
Pcrud returns columns as functions:
org.shortname();
To set a new value, pass the value as an argument:
note.value(new_note_text);
The IDL service has a toHash() method that can make this easier to work with if all you're doing is reading data:
idl.toHash(org_unit); console.debug("Org unit is:", org_unit.shortname);
Note there is an option to flatten the data.
As of 3.15, there is also a way to go from a hash back to a proper IDL object:
idl.fromHash(some_object, 'aou');
The classname is the second argument. There is an optional third argument to convert booleans from 't/f
' to true/false