Search code examples
angularruntime-error

Template parse errors: binding property's (Angular, Carbon)


I'm following the Carbon Design System Angular Tutorial. I'm trying to increment the repositories page implemented during the tutorial. My goal is to use the 'with toolbar' from table angular stories.

I'm facing these runtime property's binding errors regarding the ibm-table-toolbar and ibm-overflow-menu. See the image below:

enter image description here

repositories.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';

import { RepositoriesRoutingModule } from './repositories-routing.module';
import { RepoPageComponent } from './repo-page/repo-page.component';
import {
    GridModule,
    TableModule,
    SearchModule,
    LinkModule,
    PaginationModule,
    PanelModule,
    ToggleModule,
    ButtonModule,
    DialogModule,
    NFormsModule
} from 'carbon-components-angular';

import {
    SettingsModule,
    DeleteModule,
    FilterModule,
    SaveModule,
    DownloadModule,
    AddModule
} from '@carbon/icons-angular';

import { RepoTableComponent } from './repo-table/repo-table.component';
// import { Button } from 'protractor';


@NgModule({
    declarations: [RepoPageComponent, RepoTableComponent],
    imports: [
        CommonModule,
        RepositoriesRoutingModule,
        GridModule,
        TableModule,
        LinkModule,
        PaginationModule,
        PanelModule,
        ToggleModule,
        ButtonModule,
        SettingsModule,
        DeleteModule,
        FilterModule,
        SaveModule,
        DownloadModule,
        AddModule,
        SearchModule,
        FormsModule,
        DialogModule,
        NFormsModule
    ]
})
export class RepositoriesModule { }

repo-table.component.html

<ibm-table-container>
    <ibm-table-header>
        <h4 ibmTableHeaderTitle>Carbon Repositories</h4>
        <p ibmTableHeaderDescription>A collection of public Carbon repositories.</p>
    </ibm-table-header>
    <ibm-table-toolbar [model]="model" [batchText]="null" [size]="md" (cancel)="cancelMethod()" #toolbar>
        <ibm-table-toolbar-actions>
            <button ibmButton="primary" [tabindex]="toolbar.selected ? 0 : -1">
                Delete
                <ibm-icon-delete size="16" class="bx--btn__icon"></ibm-icon-delete>
            </button>
            <button ibmButton="primary" [tabindex]="toolbar.selected ? 0 : -1">
                Save
                <ibm-icon-save size="16" class="bx--btn__icon"></ibm-icon-save>
            </button>
            <button ibmButton="primary" [tabindex]="toolbar.selected ? 0 : -1">
                Download
                <ibm-icon-download size="16" class="bx--btn__icon"></ibm-icon-download>
            </button>
        </ibm-table-toolbar-actions>
        <ibm-table-toolbar-content *ngIf="!toolbar.selected">
            <ibm-table-toolbar-search ngDefaultControl [expandable]="true" [(ngModel)]="searchModel">
            </ibm-table-toolbar-search>
            <ibm-overflow-menu triggerClass="bx--toolbar-action" [customTrigger]="customTrigger" placement="bottom"
                [offset]="size === 'sm' ? null : offset">
                <ibm-overflow-menu-option>Option 1</ibm-overflow-menu-option>
                <ibm-overflow-menu-option>Option 2</ibm-overflow-menu-option>
                <ibm-overflow-menu-option disabled="true">Disabled</ibm-overflow-menu-option>
                <ibm-overflow-menu-option type="danger">Danger option</ibm-overflow-menu-option>
            </ibm-overflow-menu>
            <button ibmButton="primary" size="sm" [tabindex]="toolbar.selected ? -1 : 0">
                Primary button<ibm-icon-add size="20" class="bx--btn__icon"></ibm-icon-add>
            </button>
        </ibm-table-toolbar-content>
    </ibm-table-toolbar>
    <ibm-table [skeleton]="skeleton" [model]="skeleton ? skeletonModel : model" [showSelectionColumn]="true">
    </ibm-table>
    <ibm-pagination [model]="model" (selectPage)="selectPage($event)"></ibm-pagination>
</ibm-table-container>

<ng-template #linkTemplate let-data="data">
    <ul style="display: flex">
        <li>
            <a ibmLink [href]="data.github">Github</a>
        </li>
        <li *ngIf="data.homepage">
            <span>&nbsp;|&nbsp;</span>
            <a ibmLink [href]="data.homepage">HomePage</a>
        </li>
    </ul>
</ng-template>

<ibm-panel [expanded]="showSidePanel">
    <ibm-toggle [label]="Teste" [checked]="showSidePanel" (change)="toggleSideBarVisibility()">
    </ibm-toggle>
</ibm-panel>

repo-table.component.ts

import {
    Component,
    OnInit,
    ViewChild,
    TemplateRef
} from '@angular/core';

import {
    Table,
    TableModel,
    TableItem,
    TableHeaderItem,
} from 'carbon-components-angular';
import { Apollo } from 'apollo-angular';
import gql from 'graphql-tag';

@Component({
    selector: 'app-repo-table',
    templateUrl: './repo-table.component.html',
    styleUrls: ['./repo-table.component.scss']
})
export class RepoTableComponent implements OnInit {
    data = [];
    model: TableModel;
    skeletonModel = Table.skeletonModel(10, 6);
    skeleton = true;
    showSidePanel = false;
    searchModel = '';
    batchText = {
        "SINGLE": "1 item selected",
        "MULTIPLE": "{{count}} items selected"
      };
    size = 'md';

    @ViewChild('linkTemplate', null)
    protected linkTemplate: TemplateRef<any>;

    constructor(private apollo: Apollo) { }

    ngOnInit() {
        this.model = new TableModel();
        this.model.header = [
            new TableHeaderItem({data: 'Name'}),
            new TableHeaderItem({data: 'Created'}),
            new TableHeaderItem({data: 'Updated'}),
            new TableHeaderItem({data: 'Open Issues'}),
            new TableHeaderItem({data: 'Stars'}),
            new TableHeaderItem({data: 'Links'})
        ];

        this.apollo.watchQuery({
            query: gql`
              query REPO_QUERY {
                # Let's use carbon as our organization
                organization(login: "carbon-design-system") {
                  # We'll grab all the repositories in one go. To load more resources
                  # continuously, see the advanced topics.
                  repositories(first: 75, orderBy: { field: UPDATED_AT, direction: DESC }) {
                    totalCount
                    nodes {
                      url
                      homepageUrl
                      issues(filterBy: { states: OPEN }) {
                        totalCount
                      }
                      stargazers {
                        totalCount
                      }
                      releases(first: 1) {
                        totalCount
                        nodes {
                          name
                        }
                      }
                      name
                      updatedAt
                      createdAt
                      description
                      id
                    }
                  }
                }
              }
            `
        })
        .valueChanges.subscribe((response: any) => {
            if (response.error) {
                const errorData = [];
                errorData.push([
                    new TableItem({data: 'error!' })
                ]);
                this.model.data = errorData;
            } else if (response.loading) {
                this.skeleton = true;
            } else {
                // If we're here, we've got our data!
                this.data = response.data.organization.repositories.nodes;
                this.model.pageLength = 10;
                this.model.totalDataLength = response.data.organization.repositories.totalCount;
                this.selectPage(1);
            }
        });
    }

    selectPage(page) {
        const offset = this.model.pageLength * (page - 1);
        const pageRawData = this.data.slice(offset, offset + this.model.pageLength);
        this.model.data = this.prepareData(pageRawData);
        this.model.currentPage = page;
    }

    prepareData(data) {
        this.skeleton = false;
        const newData = [];

        for (const datum of data) {
            newData.push([
                new TableItem({ data: datum.name/* , expandedData: datum.description  */}),
                new TableItem({ data: new Date(datum.createdAt).toLocaleDateString() }),
                new TableItem({ data: new Date(datum.updatedAt).toLocaleDateString() }),
                new TableItem({ data: datum.issues.totalCount }),
                new TableItem({ data: datum.stargazers.totalCount }),
                new TableItem({
                    data: {
                        github: datum.url,
                        homepage: datum.homepageUrl
                    },
                    template: this.linkTemplate
                })
            ]);
        }
        return newData;
    }

    toggleSideBarVisibility() {
        this.showSidePanel = !this.showSidePanel;
    }
}

My forked repo of the tutorial with the branch trying to implement the increments.

I'm trying to understand what I'm doing wrong. I think is regarding imports and declarations... I'm really lost about these.


This is what I see on VSCode, after installing some plugins for angular. enter image description here

Also, the IntelliSense suggests this:

Can't bind to 'size' since it isn't a known property of 'ibm-table-toolbar'.

  1. If 'ibm-table-toolbar' is an Angular component and it has 'size' input, > then verify that it is part of this module.
  2. If 'ibm-table-toolbar' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
  3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component.

Solution

  • After few days of smashing my keyboard with my own head. I've finally got an insight, and decide to further investigate the code of the problematic components (on my local node modules). Of course, these attributes are not expected, because of the version I were installed. So in the end was only a matter of updating the carbon angular components dependecy.