@dilbert

@dilbert

Forum Replies Created

Viewing 5 posts - 1 through 5 (of 5 total)
  • Author
    Posts
  • in reply to: Add angular component to tab #104397
    dilbert
    Participant

    That works.  Thanks!

    in reply to: Add angular component to tab #104394
    dilbert
    Participant

    The other thing I’ve tried is to use an ngFor to define the tabs:

    <smart-tabs #tabs id="tabs" class="demoTabsShort" [closeButtons]="true" [closeButtonMode]="'selected'"
    [addNewTab]="true" (addNewTabClick)="onAddNewTabClick($event)" [reorder]="true">
        <smart-tab-item *ngFor="let tab of tabNames" [label]="tab"><app-thing></app-thing></smart-tab-item>
    </smart-tabs>

    Where tabNames is just a list of strings.

    When a new tab is added (by appending a new string to the tabNames array), the content of the new tab is the new component. However, the label is not updated and there is an error in the console:

    core.mjs:8506 ERROR TypeError: Cannot read properties of undefined (reading 'firstElementChild')
        at BaseElement._updateTabLabel (smart.tabs.js:34:65344)
        at BaseElement.propertyChangedHandler (smart.tabs.js:34:1110)
        at t.updateProperty (smart.button.js:34:75016)
        at BaseElement.set [as label] (smart.button.js:34:76150)
        at set label [as label] (smart-webcomponents-…ular-tabs.js:771:54)
        at Object.ngOnChangesSetInput [as setInput] (core.mjs:1586:26)
        at setInputsForProperty (core.mjs:11738:17)
        at elementPropertyInternal (core.mjs:10874:9)
        at Module.ɵɵproperty (core.mjs:13637:9)
        at AppComponent_smart_tab_item_6_Template (app.component.html:5:50)
    • This reply was modified 1 year, 9 months ago by dilbert.
    in reply to: Add angular component to tab #104393
    dilbert
    Participant

    Here is an example that illustrates the issue. The first 2 tabs get a dynamic component, but those that are added later do not.

    Template:

    <div>Num of smart-tab-items: {{smartItems.length}}</div>
    <div>Num of tabs: {{numTabs}}</div>
    <smart-tabs #tabs id="tabs" class="demoTabsShort" [closeButtons]="true" [closeButtonMode]="'selected'"
    [addNewTab]="true" (addNewTabClick)="onAddNewTabClick($event)" [reorder]="true">
        <smart-tab-item [label]="'Tab_1'"><ng-container app-view-ref></ng-container></smart-tab-item>
        <smart-tab-item [label]="'Tab_2'"><ng-container app-view-ref></ng-container></smart-tab-item>
    </smart-tabs>

    Main component:

    import { Component, AfterViewInit, ViewChildren, QueryList, ViewChild } from '@angular/core';
    import { TabItemComponent, TabsComponent } from 'smart-webcomponents-angular/tabs';
    import { ThingComponent } from './thing.component';
    import { ViewRefAnchorDirective } from './view-ref-anchor.directive';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css']
    })
    export class AppComponent implements AfterViewInit {
    
      // I am expecting this list to be updated when new tabs are added.
      @ViewChildren(TabItemComponent) smartItems = new QueryList();
    
      @ViewChildren(ViewRefAnchorDirective) anchors = new QueryList();
    
      @ViewChild('tabs', {read: TabsComponent, static: false}) tabs!: TabsComponent;
    
      numTabs = 0;
    
      ngAfterViewInit(): void {
        this.tabs.getTabs().then(tabs => {
          this.numTabs = tabs.length;
        });
    
        this.anchors.forEach(tab => this.loadComponent(tab));
      }
    
      onAddNewTabClick(event: Event) {
        this.tabs.getTabs().then(tabs => {
          this.numTabs = tabs.length;
    
          // At this point this.smartItems only has the original 2 smart-tab-items
          // It would appear the new tabs are not known to Angular since they aren't
          // added to the QueryList.
    
          // this.anchors also only has the original 2.  this.anchors.last references
          // the second tab.  Additional tabs do not get a new component.
          this.loadComponent(this.anchors.last);
        });
      }
    
      loadComponent(viewRefAnchor: ViewRefAnchorDirective) {
        viewRefAnchor.viewContainerRef.clear();
        viewRefAnchor.viewContainerRef.createComponent(ThingComponent);
      }
    }

    Anchor directive:

    import { Directive, ViewContainerRef } from "@angular/core";
    /**
     * An directive to expose the ViewContainerRef to allow components to be dynamically
     * created and added.
     */
    @Directive({
      selector: '[app-view-ref]'
    })
    export class ViewRefAnchorDirective {
    
      constructor(public viewContainerRef: ViewContainerRef) { }
    
    }

    Dynamic component:

    import { Component, OnInit } from '@angular/core';
    
    @Component({
      selector: 'app-thing',
      template: '<p>test-component works!</p>'
    })
    export class ThingComponent implements OnInit {
    
      constructor() { }
    
      ngOnInit(): void {
      }
    
    }
    in reply to: Add angular component to tab #104388
    dilbert
    Participant

    With that method I need the ​ViewContainerRef for the containing component which I can easily do by adding a custom anchor to smart-tab-item to expose it.  However, we a new tab is added via the built in add button, the new smart-tab-item doesn’t have this tag.  It also doesn’t get added to a @ViewChildren QueryList. (i.e. @ViewChildren(TabItemComponent) items: QueryList<TabItemComponent>).  The items list is never updated with any smart-tab-items created using the add tab button.

    Is there an easy way to get ViewContainerRef for the dynamically added smart items?

    in reply to: Add angular component to tab #104386
    dilbert
    Participant

    The mentioned help topic does work, however, as of Angular 15 the ComponentFactoryResolver is deprecated.  Is there a newer method?  I’m hesitant to base new software off of something that could be removed in the future.

Viewing 5 posts - 1 through 5 (of 5 total)