Angular Dart模板调用库定义的String扩展方法失败,如何解决?
我给String类编写了扩展方法,尝试在Angular Dart模板中调用时,Web应用构建失败,提示找不到该方法。相关代码及错误信息如下:
问题代码示例
String扩展文件 string_utils.dart
extension NullChecking on String? { bool isNullOrEmpty() => this?.isEmpty ?? true; bool isBlank() => this?.trim().isNullOrEmpty() ?? true; bool isNotBlank() => !this.isBlank(); } extension BlankChecking on String { bool isNotBlank() => !this.isBlank(); }
库文件 facade.dart
library facade; export 'src/string_utils.dart';
组件及模板代码
import 'package:facade/facade.dart'; import 'package:ngdart/angular.dart'; @Component( selector: 'my-app', template: '<h1>Hello {{name}}</h1><div>Name.isBlank(): {{name.isBlank()}}</div>', ) class AppComponent { var name = 'Angular'; }
构建错误信息
[SEVERE] build_web_compilers:ddc on lib/app_component.template.ddc.module: Error compiling dartdevc module:angular_tour_of_heroes|lib/app_component.template.sound.ddc.js
packages/angular_tour_of_heroes/app_component.template.dart:51:67: Error: The method 'isBlank' isn't defined for the class 'String'.
Try correcting the name to the name of an existing method, or defining a method named 'isBlank'.
this._textBinding_5.updateText(import9.interpolate0(_ctx.name.isBlank())) /* REF:asset:angular_tour_of_heroes/lib/app_component.dart:172:190 */;
问题原因
Angular Dart的模板编译器在生成模板对应的Dart代码时,不会自动关联组件类中导入的扩展方法——模板表达式的代码是独立生成的,默认不会包含组件导入的扩展定义。
解决方法
方法1:在组件类中包装扩展方法
在组件类中创建一个调用扩展方法的包装函数,模板中直接调用这个包装函数即可:
import 'package:facade/facade.dart'; import 'package:ngdart/angular.dart'; @Component( selector: 'my-app', template: '<h1>Hello {{name}}</h1><div>Name.isBlank(): {{isNameBlank()}}</div>', ) class AppComponent { var name = 'Angular'; bool isNameBlank() => name.isBlank(); }
方法2:使用自定义管道封装逻辑
将扩展方法的逻辑封装成Angular管道,模板中通过管道语法调用:
- 定义管道类:
import 'package:facade/facade.dart'; import 'package:ngdart/angular.dart'; @Pipe('isBlank') class IsBlankPipe extends PipeTransform { bool transform(String? value) => value.isBlank(); }
- 在组件中声明并使用该管道:
import 'package:facade/facade.dart'; import 'package:ngdart/angular.dart'; import 'is_blank_pipe.dart'; @Component( selector: 'my-app', template: '<h1>Hello {{name}}</h1><div>Name.isBlank(): {{name | isBlank}}</div>', pipes: [IsBlankPipe], ) class AppComponent { var name = 'Angular'; }
方法3:强制模板编译器导入扩展(不推荐)
如果希望直接在模板中调用扩展方法,需要让模板生成的代码显式导入扩展文件。可以通过在组件类中添加export语句,或者修改构建配置强制导入,但这种方式依赖Angular Dart的内部构建机制,稳定性较差,不建议在生产环境使用。
内容的提问来源于stack exchange,提问作者Zufar Muhamadeev

