@muraai/mnl-form 0.0.1-alpha-2edbad0 → 0.0.1-alpha-10829d9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4524,14 +4524,44 @@ class MnlFormHelperTextInputComponent extends FieldType$1 {
4524
4524
  get defaultHelperText() {
4525
4525
  return this.to['helperProps']?.['defaultHelperText'] || '';
4526
4526
  }
4527
+ // Get value from primary model (answers)
4528
+ get originalValue() {
4529
+ const fieldKey = this.field.key;
4530
+ return this.field.model?.[fieldKey];
4531
+ }
4532
+ // Get/Set value from secondary model (helper)
4533
+ get helperModel() {
4534
+ return (this.to['helperModel'] ||
4535
+ this.props['helperModel'] ||
4536
+ this.options?.formState?.['helperModel']);
4537
+ }
4538
+ get helperKey() {
4539
+ return this.to['helperKey'] || this.field.key;
4540
+ }
4541
+ get currentHelperValue() {
4542
+ if (this.helperModel && this.helperKey) {
4543
+ return this.helperModel[this.helperKey];
4544
+ }
4545
+ return '';
4546
+ }
4547
+ set currentHelperValue(value) {
4548
+ if (this.helperModel && this.helperKey) {
4549
+ this.helperModel[this.helperKey] = value;
4550
+ }
4551
+ }
4527
4552
  constructor(cdr) {
4528
4553
  super();
4529
4554
  this.cdr = cdr;
4530
4555
  this.checked = false;
4531
4556
  }
4532
4557
  ngOnInit() {
4558
+ // Initialize helper form control with value from helper model
4559
+ this.helperFormControl = new FormControl(this.currentHelperValue || '');
4560
+ // Subscribe to changes in helper form control and update helper model
4561
+ this.helperFormControl.valueChanges.subscribe((value) => {
4562
+ this.currentHelperValue = value;
4563
+ });
4533
4564
  this.setupDefaultField();
4534
- // If mode is helper, set up the initial state based on scoring
4535
4565
  if (this.to['enableHelper']) {
4536
4566
  this.setCorrectValue();
4537
4567
  this.determineInitialState();
@@ -4539,6 +4569,16 @@ class MnlFormHelperTextInputComponent extends FieldType$1 {
4539
4569
  }
4540
4570
  toggleSlide() {
4541
4571
  this.checked = !this.checked;
4572
+ if (this.checked) {
4573
+ // When toggle is opened, check if helper field is empty
4574
+ const currenthelper = this.helperFormControl.value;
4575
+ if (!currenthelper || currenthelper.trim() === '') {
4576
+ this.helperFormControl.setValue(this.defaultHelperText);
4577
+ }
4578
+ }
4579
+ else {
4580
+ this.helperFormControl.setValue('');
4581
+ }
4542
4582
  this.cdr.detectChanges();
4543
4583
  }
4544
4584
  setupDefaultField() {
@@ -4548,7 +4588,6 @@ class MnlFormHelperTextInputComponent extends FieldType$1 {
4548
4588
  ...fieldConfig,
4549
4589
  key: this.field.key || fieldConfig.key || 'defaultKey',
4550
4590
  formControl: this.formControl,
4551
- // Add required properties that formly expects
4552
4591
  modelOptions: fieldConfig.modelOptions || this.field.modelOptions || {},
4553
4592
  validators: fieldConfig.validators || this.field.validators || {},
4554
4593
  asyncValidators: fieldConfig.asyncValidators || this.field.asyncValidators || {},
@@ -4559,7 +4598,6 @@ class MnlFormHelperTextInputComponent extends FieldType$1 {
4559
4598
  fieldGroupClassName: fieldConfig.fieldGroupClassName ||
4560
4599
  this.field.fieldGroupClassName ||
4561
4600
  '',
4562
- // Inherit parent field's form and model
4563
4601
  parent: this.field.parent,
4564
4602
  options: this.field.options,
4565
4603
  model: this.field.model,
@@ -4572,12 +4610,12 @@ class MnlFormHelperTextInputComponent extends FieldType$1 {
4572
4610
  switch (this.to['scoring']?.['criteria']) {
4573
4611
  case 'exactMatch':
4574
4612
  if (Array.isArray(this.to['scoring']?.['answer']) &&
4575
- !this.to['scoring']?.['answer'].includes(this.to['value'])) {
4613
+ !this.to['scoring']?.['answer'].includes(this.originalValue)) {
4576
4614
  this.checked = true;
4577
4615
  }
4578
4616
  break;
4579
4617
  case 'range':
4580
- const answer = this.to['value'];
4618
+ const answer = this.originalValue;
4581
4619
  const num = typeof answer === 'number' ? answer : Number(answer);
4582
4620
  const correct = Number.isFinite(num) &&
4583
4621
  num >= this.to['scoring']?.['answer'].min &&
@@ -4589,28 +4627,44 @@ class MnlFormHelperTextInputComponent extends FieldType$1 {
4589
4627
  }
4590
4628
  }
4591
4629
  setCorrectValue() {
4630
+ const currentHelperValue = this.currentHelperValue;
4631
+ // If helper already has a value (user edited), don't override
4632
+ if (currentHelperValue && currentHelperValue.trim() !== '') {
4633
+ return;
4634
+ }
4592
4635
  switch (this.to['scoring']?.['criteria']) {
4593
4636
  case 'attempted':
4594
- this.formControl?.setValue(this.defaultHelperText);
4637
+ // For attempted, set defaultHelperText
4638
+ this.helperFormControl.setValue('');
4595
4639
  break;
4596
4640
  case 'exactMatch':
4597
- if (Array.isArray(this.to['scoring']?.['answer']) &&
4598
- !this.to['scoring']?.['answer'].includes(this.to['value'])) {
4599
- this.formControl?.setValue(this.defaultHelperText);
4641
+ if (Array.isArray(this.to['scoring']?.['answer'])) {
4642
+ if (this.to['scoring']?.['answer'].includes(this.originalValue)) {
4643
+ // Answer is correct - set empty value in helper
4644
+ this.helperFormControl.setValue('');
4645
+ }
4646
+ else {
4647
+ // Answer is incorrect - set defaultHelperText in helper
4648
+ this.helperFormControl.setValue(this.defaultHelperText);
4649
+ }
4600
4650
  }
4601
4651
  break;
4602
4652
  case 'range':
4603
- const answer = this.to['value'];
4653
+ const answer = this.originalValue;
4604
4654
  const num = typeof answer === 'number' ? answer : Number(answer);
4605
4655
  const correct = Number.isFinite(num) &&
4606
4656
  num >= this.to['scoring']?.['answer'].min &&
4607
4657
  num <= this.to['scoring']?.['answer'].max;
4608
- if (!correct) {
4609
- this.formControl?.setValue(this.defaultHelperText);
4658
+ if (correct) {
4659
+ // Answer is correct - set empty value in helper
4660
+ this.helperFormControl.setValue('');
4661
+ }
4662
+ else {
4663
+ // Answer is incorrect - set defaultHelperText in helper
4664
+ this.helperFormControl.setValue(this.defaultHelperText);
4610
4665
  }
4611
4666
  break;
4612
4667
  default:
4613
- this.formControl?.setValue(this.defaultHelperText);
4614
4668
  break;
4615
4669
  }
4616
4670
  }
@@ -4620,20 +4674,19 @@ class MnlFormHelperTextInputComponent extends FieldType$1 {
4620
4674
  <!-- Helper Mode - Show toggle and conditional content -->
4621
4675
  <div *ngIf="to['enableHelper']">
4622
4676
  <mat-label>{{ to.label }}</mat-label>
4623
- <div *ngIf="to['value']" class="flex-row">
4624
- <span class="answer">{{to['value'] }}</span>
4677
+ <div *ngIf="originalValue" class="flex-row">
4678
+ <span class="answer">{{ originalValue }}</span>
4625
4679
  <mat-slide-toggle
4626
4680
  [(ngModel)]="checked"
4627
4681
  (toggleChange)="toggleSlide()"
4628
- >{{helperLabel}}</mat-slide-toggle
4682
+ >{{ helperLabel }}</mat-slide-toggle
4629
4683
  >
4630
4684
  </div>
4631
4685
 
4632
4686
  <mat-form-field class="textarea" appearance="outline" *ngIf="checked">
4633
4687
  <textarea
4634
4688
  matInput
4635
- [formControl]="formControl"
4636
- [formlyAttributes]="field"
4689
+ [formControl]="helperFormControl"
4637
4690
  [readonly]="to['readonly']"
4638
4691
  >
4639
4692
  </textarea>
@@ -4646,7 +4699,7 @@ class MnlFormHelperTextInputComponent extends FieldType$1 {
4646
4699
  </formly-field>
4647
4700
  </div>
4648
4701
  </div>
4649
- `, isInline: true, styles: [".helper-text-container{display:flex;flex-direction:column}.answer{font-size:12px}.textarea{margin:0!important;width:100%}.flex-row{display:flex;flex-direction:row;justify-content:space-between}.w-full{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i3$3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$3.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: FormlyModule }, { kind: "component", type: i2$1.FormlyField, selector: "formly-field", inputs: ["field"] }, { kind: "directive", type: i2$1.ɵFormlyAttributes, selector: "[formlyAttributes]", inputs: ["formlyAttributes", "id"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$3.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "ngmodule", type: MatNativeDateModule }] }); }
4702
+ `, isInline: true, styles: [".helper-text-container{display:flex;flex-direction:column}.answer{font-size:12px}.textarea{margin:0!important;width:100%}.flex-row{display:flex;flex-direction:row;justify-content:space-between}.w-full{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i3$3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$3.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: FormlyModule }, { kind: "component", type: i2$1.FormlyField, selector: "formly-field", inputs: ["field"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$3.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "ngmodule", type: MatNativeDateModule }] }); }
4650
4703
  }
4651
4704
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MnlFormHelperTextInputComponent, decorators: [{
4652
4705
  type: Component,
@@ -4666,20 +4719,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
4666
4719
  <!-- Helper Mode - Show toggle and conditional content -->
4667
4720
  <div *ngIf="to['enableHelper']">
4668
4721
  <mat-label>{{ to.label }}</mat-label>
4669
- <div *ngIf="to['value']" class="flex-row">
4670
- <span class="answer">{{to['value'] }}</span>
4722
+ <div *ngIf="originalValue" class="flex-row">
4723
+ <span class="answer">{{ originalValue }}</span>
4671
4724
  <mat-slide-toggle
4672
4725
  [(ngModel)]="checked"
4673
4726
  (toggleChange)="toggleSlide()"
4674
- >{{helperLabel}}</mat-slide-toggle
4727
+ >{{ helperLabel }}</mat-slide-toggle
4675
4728
  >
4676
4729
  </div>
4677
4730
 
4678
4731
  <mat-form-field class="textarea" appearance="outline" *ngIf="checked">
4679
4732
  <textarea
4680
4733
  matInput
4681
- [formControl]="formControl"
4682
- [formlyAttributes]="field"
4734
+ [formControl]="helperFormControl"
4683
4735
  [readonly]="to['readonly']"
4684
4736
  >
4685
4737
  </textarea>
@@ -4811,11 +4863,21 @@ class ScoringService {
4811
4863
  calculateScore(model, fields) {
4812
4864
  let totalScore = 0;
4813
4865
  let categoryResults = {};
4814
- for (const category of fields) {
4815
- const categoryLabel = category.props?.label || 'Unnamed Category';
4816
- const categoryWeight = category.props?.weight || 0;
4817
- const questions = category.fieldGroup || [];
4818
- const perQuestionWeight = categoryWeight / (questions.length || 1);
4866
+ const processCategory = (category) => {
4867
+ const categoryLabel = category.props?.label;
4868
+ const categoryWeight = category.props?.weight ?? 0;
4869
+ // Only treat as scoring category if it has a label + weight
4870
+ if (!categoryLabel || !categoryWeight) {
4871
+ // Still need to go deeper in case children have categories
4872
+ if (category.fieldGroup?.length) {
4873
+ category.fieldGroup.forEach(processCategory);
4874
+ }
4875
+ return;
4876
+ }
4877
+ const questions = (category.fieldGroup || []).filter(q => q.props?.scoring);
4878
+ if (questions.length === 0)
4879
+ return;
4880
+ const perQuestionWeight = categoryWeight / questions.length;
4819
4881
  let categoryScore = 0;
4820
4882
  for (const q of questions) {
4821
4883
  const parentKey = category.key;
@@ -4856,7 +4918,9 @@ class ScoringService {
4856
4918
  score: categoryScore,
4857
4919
  weight: categoryWeight,
4858
4920
  };
4859
- }
4921
+ };
4922
+ // start recursive walk
4923
+ fields.forEach(processCategory);
4860
4924
  return {
4861
4925
  totalScore,
4862
4926
  categoryResults,
@@ -4900,6 +4964,7 @@ class MnlFormLibComponent {
4900
4964
  ...this.options.formState,
4901
4965
  showOldValues: this.showOldValues,
4902
4966
  oldValues: this.oldValues,
4967
+ helperModel: this.helperModel,
4903
4968
  },
4904
4969
  };
4905
4970
  }
@@ -5005,7 +5070,7 @@ class MnlFormLibComponent {
5005
5070
  });
5006
5071
  }
5007
5072
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MnlFormLibComponent, deps: [{ token: i1$2.TranslateService }, { token: ScoringService }], target: i0.ɵɵFactoryTarget.Component }); }
5008
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: MnlFormLibComponent, isStandalone: true, selector: "mnl-form", inputs: { readonly: "readonly", form: "form", fields: "fields", model: "model", options: "options", userRoles: "userRoles", userCountries: "userCountries", oldValues: "oldValues", showOldValues: "showOldValues" }, outputs: { noOfTabs: "noOfTabs", scoreChange: "scoreChange" }, ngImport: i0, template: "@if(formPrepared) {\n<formly-form\n [form]=\"form\"\n [fields]=\"fields\"\n [model]=\"model\"\n [options]=\"options\"\n (modelChange)=\"onModelChange($event)\"\n class=\"mnl-formly-form\"\n></formly-form>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: CommonsModule }, { kind: "ngmodule", type: FormlyModule }, { kind: "component", type: i2$1.FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: FormlyMatTextAreaModule }, { kind: "ngmodule", type: FormlyMatInputModule }, { kind: "ngmodule", type: FormlyMatCheckboxModule }, { kind: "ngmodule", type: FormlyMatRadioModule }] }); }
5073
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: MnlFormLibComponent, isStandalone: true, selector: "mnl-form", inputs: { readonly: "readonly", form: "form", fields: "fields", model: "model", helperModel: "helperModel", options: "options", userRoles: "userRoles", userCountries: "userCountries", oldValues: "oldValues", showOldValues: "showOldValues" }, outputs: { noOfTabs: "noOfTabs", scoreChange: "scoreChange" }, ngImport: i0, template: "@if(formPrepared) {\n<formly-form\n [form]=\"form\"\n [fields]=\"fields\"\n [model]=\"model\"\n [options]=\"options\"\n (modelChange)=\"onModelChange($event)\"\n class=\"mnl-formly-form\"\n></formly-form>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: CommonsModule }, { kind: "ngmodule", type: FormlyModule }, { kind: "component", type: i2$1.FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: FormlyMatTextAreaModule }, { kind: "ngmodule", type: FormlyMatInputModule }, { kind: "ngmodule", type: FormlyMatCheckboxModule }, { kind: "ngmodule", type: FormlyMatRadioModule }] }); }
5009
5074
  }
5010
5075
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MnlFormLibComponent, decorators: [{
5011
5076
  type: Component,
@@ -5029,6 +5094,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
5029
5094
  type: Input
5030
5095
  }], model: [{
5031
5096
  type: Input
5097
+ }], helperModel: [{
5098
+ type: Input
5032
5099
  }], options: [{
5033
5100
  type: Input
5034
5101
  }], userRoles: [{