AngularDart: cannot cast to a material component

Issue

I have a dart app that contains a template with a material-checkbox which I am unable to use in my component. Here is a simple template to demonstrate the problem (two_boxes.html):

<!--
Simple HTML to test checkboxes
-->

<input type="checkbox" id="cb0">
<label>Standard Checkbox</label>

<material-checkbox label="Material Checkbox" id="cb1">
</material-checkbox>

<button (click)="doTest()">Test</button>

and the corresponding component in which I try to use the checkboxes (two_boxes.dart). I can use the standard checkbox in a cast as expected but cannot find a way to do the same with the material checkbox:

// Component for testing

import 'package:angular/angular.dart';
import 'package:angular_components/angular_components.dart';

import 'dart:html';

@Component(
    selector: 'two-boxes',
    templateUrl: 'two_boxes.html',
    directives: const [MaterialCheckboxComponent],
    pipes: const [
      COMMON_PIPES
    ])
class TwoBoxes {

  // Get the the two checkboxes and see if they are checked
  void doTest() {
    var checkbox_standard = querySelector("#cb0");
    print(checkbox_standard.runtimeType.toString()); // InputElement
    print((checkbox_standard as CheckboxInputElement).checked); // Succeeds

    var checkbox_material = querySelector("#cb1");
    print(checkbox_material.runtimeType.toString()); // HtmlElement
    print((checkbox_material as MaterialCheckboxComponent).checked); // Error!
  }
}

The last statement fails when I run the app in Dartium following a “pub serve” (no errors) with:

VM54:1 EXCEPTION: type 'HtmlElementImpl' is not a subtype of type
MaterialCheckboxComponent' in type cast where HtmlElementImpl is 
from dart:html MaterialCheckboxComponent is from   
package:angular_components/src/components/
material_checkbox/material_checkbox.dart

Clearly this way of casting does not work. I searched for hours how to solve this error and find the correct way to do this but obviously in the wrong places. What am I missing here? I am using Dart VM version 1.24.2.

Solution

There is no way to get the component instance from an element queried this way.

You can use @ViewChild()

class TwoBoxes implements AfterViewInit {

  @ViewChild(MaterialCheckboxComponent) MaterialCheckboxComponent cb;

  ngAfterViewInit() {
    print(cb.checked);
  }

to get a specific one if you have more than one, you can use a template variable

<material-checkbox #foo label="Material Checkbox">

with

@ViewChild('foo') MaterialCheckboxComponent cb;

You can find more information about this topic in this TypeScript answer angular 2 / typescript : get hold of an element in the template

The syntax is a bit different (type annotations on the right and {} around the optional read parameter, which are not used in Dart.

Answered By – Günter Zöchbauer

Answer Checked By – David Goodson (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *