angulardart / angular

Fast and productive web framework provided by Dart
https://pub.dev/packages/angular
MIT License
1.83k stars 230 forks source link

Angular Dart & attribute value should be passed as any value. #1980

Closed Iskren1990 closed 3 years ago

Iskren1990 commented 3 years ago

Thank you for taking the time to file an issue!

In order to route, prioritize, and act on this as soon as possible please include:

[**@** abrites_ui]$ dart --version Dart SDK version: 2.14.2 (stable) (Wed Sep 15 12:32:06 2021 +0200) on "linux_x64"

N/A

N/A

Missing some or all of the above might make the issue take longer or be impossible to act on.


For questions consider using Stack Overflow instead: https://stackoverflow.com/questions/tagged/angular-dart

Also consider our Gitter channel for light-weight/quick discussions: https://gitter.im/angulardart/community


I have migrated to dart null-safe version and Angular Dart 7 and i am facing the following:


packages/abrites_ui/datepicker/datepicker_input.template.dart:368:60: Error: The argument type 'int' can't be assigned to the parameter type 'String?'. import19.updateAttribute(this.rootElement, 'months', currVal_18);

packages/abrites_ui/pagination/pagination.template.dart:281:62: Error: The argument type 'bool' can't be assigned to the parameter type 'String?'. import18.updateAttribute(this.rootElement, 'disabled', currVal_7);


The above behavior is related to "updateAttribute" Fn defined in " angular/angular/lib/src/runtime/dom_helpers.dart":


@dart2js.noInline void updateAttribute( Element element, String attribute, String? value, ) { if (value == null) { element.removeAttribute(attribute); } else { setAttribute(element, attribute, value); } domRootRendererIsDirty = true; }


As per MDN documentation i believe that the behavior is unexpected:

ref: https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute


Syntax

Element.setAttribute(name, value);

Parameters

name

A DOMString specifying the name of the attribute whose value is to be set. The attribute name is automatically converted to all lower-case when setAttribute() is called on an HTML element in an HTML document.

value

A DOMString containing the value to assign to the attribute. Any non-string value specified is converted automatically into a string.

As per HTML standard i believe that the behavior is unexpected:

ref: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#boolean-attributes


2.3.2 Boolean attributes

A number of attributes are boolean attributes. The presence of a boolean attribute on an element represents the true value, and the absence of the attribute represents the false value.

If the attribute is present, its value must either be the empty string or a value that is an ASCII case-insensitive match for the attribute's canonical name, with no leading or trailing whitespace.


ref: https://html.spec.whatwg.org/multipage/dom.html#attributes


3.2.4.1 Attributes

An attribute value is a string. Except where otherwise specified, attribute values on HTML elements may be any string value, including the empty string, and there is no restriction on what text can be specified in such attribute values.


Tomucha commented 2 years ago

@Iskren1990 Hi, did you solve this or do you have some workaround for it? Thanks!!!

Iskren1990 commented 2 years ago

@Tomucha Hi, i had wokaround since addressing the issue. You can either create custom directive with multiple selectors:

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

@Directive( selector: ''' [success], [warning], [danger], ... ... ... [lowercase] ''', ) class AttributeDirective {} `

import, and add it as directive in the directive list, it in each component with custom attribute selectors:

`import 'package:abrites_ui/directives/class_directive.dart'; import 'package:abrites_ui/loader/loader.dart'; import 'package:angular/angular.dart'; import 'package:angular_router/angular_router.dart';

/// Example /// html /// <abrites-button (trigger)="myAction()"></abrites-button> /// <!-- as internal link --> /// <abrites-button [link]="'/home'"></abrites-button> /// @Component( selector: 'abrites-button', templateUrl: 'button.html', styleUrls: ['button.css'], directives: [ NgIf, NgTemplateOutlet, AbritesLoader, RouterLink, AttributeDirective, ], changeDetection: ChangeDetectionStrategy.OnPush, )`

Second one , though harder to be implemented, is a better approach. You would have to walk through each template and annotate the attributes as such:

<abrites-button *ngIf="manager.isVehicleOnline(vehicle)" [attr.round] [attr.flat] [attr.small] [attr.light]

Tomucha commented 2 years ago

Thanks!