// Alternative à Rendern pour des intégrations plus complexes. // Le contenu des divers champs peut ici être mixé à l'affichage ou encore affiché plusieurs fois... import { DatasRenders } from "../interfaces"; const errors=require("../errors.js"); interface DatasRendersSettings { allBegining: string; allEnding: string; linesBegining?: string, linesEnding?: string, fieldsNamesDisplaying?: string; // ##n## sera remplacé par le nom du nième champ, etc. datasLinesDisplaying: string;// ##n## sera remplacé par la valeur du nième champ, etc. } interface FieldRender { name: string; // nom du champ concerné. rend2HTML(lineValues: {[index: string]:string} ) : string; // fonction spécifique appelée avant d'injecter la valeur de ce champ dans datasLinesDisplaying } export class MixedFieldsRender implements DatasRenders { private _fields: string[]=[]; public settings: DatasRendersSettings; public fieldRenders: FieldRender[]=[]; public datas: {[index: string]:string}[]=[]; constructor(settings: DatasRendersSettings) { this.settings=settings; } // Les données fournies au Render peuvent être vides du fait de l'action des filtres ou encore de la pagination... // Mais les noms des champ doivent être fournis. set fields(fields: string[]) { if(fields.length === 0) throw new Error(errors.renderNeedFields); else this._fields=fields; } get fields() : string[] { return this._fields; } public rend2HTML() : string { if(this._fields.length === 0) throw new Error(errors.renderNeedFields); else { let datasHTML=this.settings.allBegining; // Création d'une éventuelle entête : if(this.settings.fieldsNamesDisplaying !== undefined) { // Dans le cas de champs mixés, tous les champs utilisés ne sont pas forcément listés en entête. // Il suffit alors qu'ils soient absent de fieldsNamesDisplaying. let fieldsNamesRend=this.settings.fieldsNamesDisplaying; for(let i=0; i< this._fields.length; i++) fieldsNamesRend=fieldsNamesRend.replace("##"+i+"##", this._fields[i]); datasHTML+=fieldsNamesRend; } if(this.settings.linesBegining !== undefined) datasHTML+=this.settings.linesBegining; // Suivant les objets/lignes, les champs peuvent se trouver dans un ordre différent. // Ou encore certains peuvent manquer, être en trop... // Mais tous les champs présents dans "fields" doivent être traités en respectant leur ordre pour être cohérent avec l'éventuelle entête créée ci-dessus. for(let row of this.datas) { // Idem que l'entête : tous les champs ne sont pas forcément présents dans datasLinesDisplaying. let lineRend=this.settings.datasLinesDisplaying; for(let i=0; i< this._fields.length; i++) { const currentField=this._fields[i]; if(row[currentField] !== undefined) // champ renseigné pour cet enregistrement { // Par défaut, l'emplacement dans datasLinesDisplaying sera remplacé par la valeur renseignée : let rowRend=row[currentField]; // Sauf si une fonction de pré-traitement a été fournie pour ce champ : const render = this.fieldRenders.find(function(item) { return item.name === currentField; }); if(render !== undefined) rowRend=render.rend2HTML(row); lineRend=lineRend.replace(new RegExp("##"+i+"##", "g"), rowRend); // RegExp, car bug TS avec replaceAll (parce que target = es5 ?). } else // si ce champ n'est pas renseigné, il faut tout de même supprimer l'indicateur de son emplacement : lineRend=lineRend.replace(new RegExp("##"+i+"##", "g"), ""); } datasHTML+=lineRend; } if(this.settings.linesEnding !== undefined) datasHTML+=this.settings.linesEnding; datasHTML+=this.settings.allEnding; return datasHTML; } } } // Utile au script de tests : export { FreeDatas2HTML } from "../FreeDatas2HTML"; export { errors };