Telerik Forums
Kendo UI for Angular Forum
0 answers
24 views

Using formBuilder to create a reactive form when I noticed that it turns array properties in to the first object in the array. This is breaking my multiselect drop down as it is expecting an array.

I create a stack blitz demonstration. 

https://stackblitz.com/edit/angular-bnet6z?file=src%2Fapp%2Fapp.component.ts

This is based off of you https://www.telerik.com/kendo-angular-ui/components/dropdowns/multiselect/forms/#toc-reactive-forms demonstration where I changed the form building to use the form builder.

Multiselect then reports these errors.

  • ERROR
    1. Error: values.reduce is not a function
    2. ERROR
      1. Error: Expected values of array type. See https://www.telerik.com/kendo-angular-ui/components/dropdowns/multiselect/value-binding
      2. The workaround is to build the form manually, but it really feels like a bug in formBuilder. Is there something else that will work to prevent formBuilder from reducing arrays?

      3. John
        Top achievements
        Rank 1
        Iron
         asked on 21 Dec 2023
        2 answers
        36 views

        Hey everyone, 

        Hope this message finds you well. 

        I'm creating a grid table with Add/Edit/Delete features. Currently running into a blocker when clicking on a checkbox during an Add procedure. This action completely resets the values from the dropdown menus I've previously selected from. Any ideas as to why this behavior might be occurring? Thanks! 

        TS: 

        import { Component, OnInit } from '@angular/core';
        import { DataService } from '../../services/other_api/DataService';
        import { ErrorHandlerService } from '../../services/error-handler.service';
        import { Item } from '../../models/other_api/Item';
        import { FormBuilder, FormGroup } from '@angular/forms';
        import { SortDescriptor } from "@progress/kendo-data-query";
        import { RemoveEvent, SaveEvent } from '@progress/kendo-angular-grid';
        import { AnotherService } from '../../services/other_api/AnotherService';
        import { DifferentService } from '../../services/other_api/DifferentService';
        import { SomeService } from '../../services/other_api/SomeService';

        @Component({
          selector: 'app-client',
          templateUrl: './client.component.html',
          styleUrls: ['./client.component.scss'],
        })
        export class ClientComponent implements OnInit {
          clients: Item[] = [];
          anotherItems: string[] = [];
          differentItems: string[] = [];
          someItems: string[] = [];
          moreItems: string[] = [];
          parentItems: string[] = [];

          constructor(
            private errorHandlerService: ErrorHandlerService,
            private dataService: DataService,
            private anotherService: AnotherService,
            private differentService: DifferentService,
            private someService: SomeService,
            private formBuilder: FormBuilder,
          ) {
            this.createFormGroup = this.createFormGroup.bind(this);
          }

          public formGroup: FormGroup = this.formBuilder.group({
            Id: 0,
            ClientName: '',
            ClientKey: '',
            ParentClientName: '',
            IsParent: false,
            MarketVertical: '',
            Region: '',
            Inactive: false,
            Locale: ''
          });

          public createFormGroup = (args: any): FormGroup => {
            const item = args.isNew ? new Item(0, '', '', '', '', '', false, false, '') : args.dataItem;

            return this.formBuilder.group({
              Id: item.Id,
              ClientName: item.ClientName,
              ClientKey: item.ClientKey,
              ParentClientName: item.ParentClientName,
              IsParent: item.IsParent || false,
              MarketVertical: item.MarketVertical,
              Region: item.Region,
              Inactive: item.Inactive || false,
              Locale: item.Locale
            });
          };

          public sort: SortDescriptor[] = [
            {
              field: "Name",
              dir: "asc",
            },
          ];

          public sortChange(sort: SortDescriptor[]): void {
            this.sort = sort;
            this.getAllClients();
            this.getAnotherItems();
            this.getDifferentItems();
            this.getSomeItems();
            this.getMoreItems();
            this.getParentItems();
          }

          ngOnInit(): void {
            this.getAllClients();
            this.getAnotherItems();
            this.getDifferentItems();
            this.getSomeItems();
            this.getMoreItems();
            this.getParentItems();
          };

          login() {
            //Implementation for login
          };

          showError() {
            this.errorHandlerService.handleError("This is a test error. Stuff is super wrong.");
          }

          getClient(): void {
            this.dataService.get(1).subscribe();
          }

          getAllClients(): void {
            this.dataService.getAll().subscribe((data) => {
              this.clients = data;
            });
          }

          getAnotherItems(): void {
            this.anotherService.getAll().subscribe((data) => {
              this.anotherItems = data.map((anotherItem) => anotherItem.Name);
            });
          }

          getDifferentItems(): void {
            this.differentService.getAll().subscribe((data) => {
              this.differentItems = data.map((differentItem) => differentItem.Description);
            });
          }

          // Similar functions for other services

          saveHandler(args: SaveEvent): void {
            if (args.isNew) {
              this.dataService.create(args.dataItem).subscribe((createdData) => {
                const updateItem = this.clients.filter(element => element.ClientName === createdData.ClientName)[0];
                updateItem.Id = createdData.Id;
              });
            }
            else {
              this.dataService.update(args.formGroup.value).subscribe((updatedData) => {
                const updateItem = this.clients.filter(element => element.Id === updatedData.Id)[0];
                updateItem.ClientName = updatedData.ClientName;
                updateItem.ClientKey = updatedData.ClientKey;
                // Similar updates for other properties
              });
            }
            args.sender.closeRow(args.rowIndex);
          }

          removeHandler(args: RemoveEvent): void {
            this.dataService.delete(args.dataItem).subscribe();
          }
        }


        ------------------------------

        HTML:

        <link rel="stylesheet" href="https://unpkg.com/@progress/kendo-theme-default/dist/all.css" />
        <app-page-layout [workingArea]="body" [footer]="footer">
          <ng-template #body>
            <h1>Clients</h1>
            <kendo-grid [kendoGridReactiveEditing]="createFormGroup"
                        [kendoGridBinding]="clients"
                        [pageable]="true"
                        [sortable]="true"
                        [navigable]="true"
                        [filterable]="true"
                        [sort]="sort"
                        (sortChange)="sortChange($event)"
                        [pageSize]="10"
                        (save)="saveHandler($event)"
                        (remove)="removeHandler($event)">
              <ng-template kendoGridToolbarTemplate>
                <button kendoGridAddCommand themeColor="success">Add</button>
              </ng-template>
              <kendo-grid-column field="ClientName" title="Client Name"> </kendo-grid-column>


              <kendo-grid-column [filterable]="false" field="ClientKey" title="Client Key">
                <ng-template kendoGridEditTemplate let-dataItem="dataItem">
                  <kendo-dropdownlist [data]="clientKeys" [(ngModel)]="dataItem.ClientKey" name="ClientKey"></kendo-dropdownlist>
                </ng-template>
              </kendo-grid-column>

              <!-- Other columns-->

              <kendo-grid-column [filterable]="true" filter="boolean" field="IsParent" title="Is Parent" editor="boolean">
                <ng-template kendoGridCellTemplate let-dataItem="dataItem">
                  <input kendoCheckBox id="isParentCheckbox" type="checkbox" [checked]="dataItem.IsParent" disabled />
                </ng-template>
              </kendo-grid-column>

              <kendo-grid-column [filterable]="true" filter="boolean" field="Inactive" title="Inactive" editor="boolean">
                <ng-template kendoGridCellTemplate let-dataItem="dataItem">
                  <input kendoCheckBox id="InactiveCheckbox" type="checkbox" [checked]="dataItem.Inactive" disabled />
                </ng-template>
              </kendo-grid-column>

              <kendo-grid-command-column title="Actions" [width]="220">
                <ng-template kendoGridCellTemplate let-isNew="isNew">
                  <button kendoGridEditCommand themeColor="info">
                    Edit
                  </button>
                  <button kendoGridRemoveCommand themeColor="error">Remove</button>
                  <button kendoGridSaveCommand themeColor="success">
                    {{ isNew ? "Add" : "Update" }}
                  </button>
                  <button kendoGridCancelCommand themeColor="warning">
                    {{ isNew ? "Discard changes" : "Cancel" }}
                  </button>
                </ng-template>
              </kendo-grid-command-column>
            </kendo-grid>
          </ng-template>

          <ng-template #footer>
            <app-custom-button [buttonText]="'Login'" aria-label="Login" (onClick)="login()"></app-custom-button>
            <app-custom-button [buttonText]="'Show Error'" aria-label="Show Error" (onClick)="showError()"></app-custom-button>
          </ng-template>
        </app-page-layout>
        1 answer
        178 views
        Hello,
        I use Kendo UI Angular,
        I have a kendomulticombobox in a form, I use this combobox in several forms, and to avoid copying and pasting, I thought of setting up a separate component for that, and just call it each time I need.
        It's to say that the form has a formgroup, and that this formgroup has several formcontrols, that I get when I submit the form.
        So when I integrate my custom component, I get an error `ERROR Error: No value accessor for form control with name:` and yet it's the same formcontrol that I use before.

        Has anyone experienced this kind of problem? Or do you have any solutions please? Thanks
        Martin
        Telerik team
         answered on 15 May 2023
        0 answers
        59 views
        I have a FormArray that contains two dropdowns. When I select a value in the parent dropdown, the child dropdown values are filtered accordingly. However, when I use the "add more" button to iterate the form and select a value in the parent dropdown, it affects the child dropdown of all other iterated forms. I want to prevent this from happening so that each iterated form behaves independently of the others.
        Ankush
        Top achievements
        Rank 1
         asked on 21 Apr 2023
        0 answers
        407 views

        Hello,
        I am generating a template that contains a dynamic button panel, and I need to assign a click event to an <a> element within a dynamically generated <li> list. I get the values ​​from a Json object.
        The function value of each element of the list comes from a Json object value (fieldChildren.action), but when trying to assign the event (click)="fieldchildren.action", it is not being created correctly.
        Please help me with some indication in this regard.
        I am using kendo multistep form with angular 15

         

        <ul ngbDropdownMenu id="addoptions" aria-labelledby="Button_Add" class="dropdown-menu">
              <li *ngFor = "let campoChildren of campodisplay.children">
                            <a class="dropdown-item" (click)="campoChildren.action">{{campoChildren.name}}</a>
               </li>
        </ul>

        Saby
        Top achievements
        Rank 1
        Veteran
        Iron
         asked on 15 Mar 2023
        0 answers
        72 views

        I'm struggling to access this kendo-switch ID (in this case it should be A1) being passed to the generateSubscriptionArray function it seems to return undefined no matter what variation of attempts to access it I try, it also doesn't seem to show up on the $event if I try to pass this to the function.

        Any assistance regarding this would be really beneficial the switch is returning the relevant true/false boolean

        HTML

         

        <kendo-switch onLabel=" " offLabel=" " formControlName="A1" id="A1" (click)="generateSubscriptionArray(userPreferenceForm.controls.A1.value,
        formcontrol id as string in this case A1 should be passed here)" ></kendo-switch>


        TypeScript:

        exportclass UserPreferencesComponent implements OnInit { userPreferenceForm: FormGroup; email_address: FormControl; constructor() {} ngOnInit(): void { this.userPreferenceForm = new FormGroup({ email_address: new FormControl('', Validators.required), A1: new FormControl(false), }); }

        generateSubscriptionArray = (subscription: boolean, alertID: string): void => { if (subscription === true) { console.log(subscription, alertID); } else { console.log(subscription, alertID); } };


        Olivia
        Top achievements
        Rank 1
         asked on 03 Mar 2023
        1 answer
        104 views

        I am new at Kendo UI. Already I add the date module normally as a quick cli setup. But when I want to add another module this trough an error. 

        Example:

        Unable to load package information from the registry: Response timeout while trying to fetch https://registry.npmjs.org/@progress%2fkendo-angular-inputs (over 300000ms)

        Veselin
        Telerik team
         answered on 25 Jan 2023
        0 answers
        41 views

        [RESOLVED]

        Hello,

        I have integrated kendo grid with some details-grid using the KendoGridDetailTemplate. 
        Everything works great, but I can't find a way of hiding the [+] sign when there is nothing to show in the details component. 

        I am already using the [KendoGridDetailTemplateShowIf]="ShowDetailsCondition" but the problem i'm facing is that when the directive is called, I don't have access to the methods in my component, since "this" changes and represents the directive itself. 

                      <ng-template kendoGridDetailTemplate let-dataItem [kendoGridDetailTemplateShowIf]="showDetailsCondition">
                        <app-cash-register-main-cash-register-action-form-details
                          [invoiceHeaders]="invoiceHeaders"
                          [quoteHeaders]="quoteHeaders"
                          [shipmentHeaders]="shipmentHeaders"
                          [subscriptionHeaders]="subscriptionHeaders"
                          [orderHeaders]="orderHeaders"
                          [creditNoteHeaders]="creditNoteHeaders"
                          [document]="dataItem">
                        </app-cash-register-main-cash-register-action-form-details>
                      </ng-template>

         

          hasHeaders(dataItem): boolean {
            console.log(dataItem);
            let document = dataItem;
            const type = document.SourceEntity;
            const id = document.EntityId;
            let documentFound = [];
            switch (type) {
              case 'InvoiceHeader':
                console.log('InvoiceHeader');
                const InvoiceHeader = this.invoiceHeaders.find(q => q.Id == id);
                documentFound.push(...this.findParentDocumentFromHeader(InvoiceHeader, type));
                documentFound.push(...this.findParentDocumentFromLines(InvoiceHeader?.Lines, type));
                break;
              case 'QuoteHeader':
                console.log('QuoteHeader');
                const selectedQuoteHeader = this.quoteHeaders.find(q => q.Id == id);
                documentFound.push(...this.findParentDocumentFromHeader(selectedQuoteHeader, type));
                documentFound.push(...this.findParentDocumentFromLines(selectedQuoteHeader?.Lines, type));
                break;
              case 'SubscriptionHeader':
                console.log('SubscriptionHeader');
                const selectedSubscription = this.subscriptionHeaders.find(q => q.Id == id);
                documentFound.push(...this.findParentDocumentFromHeader(selectedSubscription, type));
                documentFound.push(...this.findParentDocumentFromLines(selectedSubscription?.Lines, type));
                break;
              case 'OrderHeader':
                console.log('OrderHeader');
                const selectedOrderHeader = this.orderHeaders.find(q => q.Id == id);
                documentFound.push(...this.findParentDocumentFromHeader(selectedOrderHeader, type));
                documentFound.push(...this.findParentDocumentFromLines(selectedOrderHeader?.Lines, type));
                break;
              case 'CreditNoteHeader':
                console.log('CreditNoteHeader');
                const selectedCreditNoteHeader = this.creditNoteHeaders.find(q => q.Id == id);
                documentFound.push(...this.findParentDocumentFromHeader(selectedCreditNoteHeader, type));
                documentFound.push(...this.findParentDocumentFromLines(selectedCreditNoteHeader?.Lines, type));
                break;
              case 'ShipmentHeader':
                console.log('ShipmentHeader');
                const selectedShipmentHeader = this.shipmentHeaders.find(q => q.Id == id);
                documentFound.push(...this.findParentDocumentFromHeader(selectedShipmentHeader, type));
                break;
            }
            if (documentFound.length > 0) {
              return true;
            }
            return false;
          }

        here is my condition function: 

          public showDetailsCondition(dataItem: MovementDocumentCustomer): boolean {
            console.log(dataItem);
            return (
              (dataItem.SourceEntity === 'InvoiceHeader' ||
                dataItem.SourceEntity === 'ShipmentHeader' ||
                dataItem.SourceEntity === 'OrderHeader') &&
              this.hasHeaders(dataItem)
            );
          }

         

        error : "this.hasHeaders is not a function" => I guess it's because "this" represent now the Directive and not my component

        How could I use custom methods/function from my component into my condition function without have it returning an error ?

        Thanks you!
        Audric 

        Audric
        Top achievements
        Rank 1
         updated question on 05 Dec 2022
        1 answer
        44 views

        Hi,

        I have a template driven form and use some kendo elements (e.g. DatePicker or Dropdownlist). The error is the same for all the Kendo widgets, I'll describe it here only for the DatePicker:

        In my component 1, there's my form and I call my sub-component where the datepicker is in it:

        <form #form="ngForm" novalidate="novalidate">

        <my-datepicker [(property)]="myProperty" [parentctrl]="this"></my-datepicker>

        ...

        </form>

         

        In my sub-component there is the kendo DatePicker:

        <kendo-datepicker #datePicker
                              calendarType="classic"
                              [attr.name]="datePickerName"
                              [(ngModel)]="dateVal"
                              [format]="'dd.MM.yyyy'"
                              (ngModelChange)="datePickerChanged()"></kendo-datepicker>

        The name of the DatePicker is set dynamically via [attr.name]. The value is inside the component:

        @Component({
          selector: 'my-datepicker',
          templateUrl: './my-datepicker.component.html',
          viewProviders: [{ provide: ControlContainer, useExisting: NgForm }],
          styleUrls: ['./my-datetimepicker.component.less']
        })
        export class MyDatepickerComponent {

        public datePickerName: string = "myName";

        }

        When I check this.parentctrl.form.form.controls[this.datePickerName], there is no form control for my datepicker. Also, when I replace it with <kendo-datepicker name="{{datePickerName}}". This problem only exists, when I set the DatePicker name dynamically. When I use a static name (<kendo-datepicker name="myName"), I can find the datePicker in the form.controls array.

        I need access to the form.controls array for validation purposes, but I need to set the name attribute dynamically from component code.

        With normal html5 elements (like input) it works. But with Kendo elements (DatePicker, Dropdownlistm ...) there is the problem in the form.controls array.

        Do you have any idea how to "refresh" the form controls array after setting the name dynamically?

        Thanks,

        Katharina

        Martin
        Telerik team
         answered on 02 Mar 2022
        1 answer
        1.0K+ views
        Hi

        I have an complex object initialize from Rest WebService with many fields and there is an Date fiel, but i could init it with patch value to kendo-datepicker

        Could you help me



        Regards

        1 json object from  MyService
        {
            "profilId": 50531,
            "surname": "3454",
            "name": "11",
            "date": "2027-12-30"
        ...
        ...
        ..
        ...
        ...

        }

        2 html

         <kendo-datepicker id = "date" formControlName = "date" class = "pull-left" >  </kendo-datepicker>

            3 component
            export class DossiersDetailDossierTabsheetSommaireFormComponent implements OnInit {
            constructor(private formBuilder: FormBuilder,
                private activatedroute: ActivatedRoute,
                private router: Router,
                private dps: MyService ) {}

            ngOnInit() {
                this.registerForm = this.formBuilder.group({
                    profilId: [''],
                    surname: [''],
                    name: [''],
        date: ['']
                });

                this.dps.getData(this.id)
                .pipe(first())
                .subscribe(x => this.registerForm.patchValue(x)); //ERROR ON Date field
            }
        }
        ixen
        Top achievements
        Rank 1
        Iron
        Iron
        Iron
         answered on 30 Sep 2021
        Top users last month
        Dominik
        Top achievements
        Rank 1
        Giuliano
        Top achievements
        Rank 1
        Dominic
        Top achievements
        Rank 1
        Glendys
        Top achievements
        Rank 1
        NoobMaster
        Top achievements
        Rank 2
        Iron
        Want to show your ninja superpower to fellow developers?
        Want to show your ninja superpower to fellow developers?