Isn't EL for Java and JSP/JSF?Yes, it is. And with Rikulo EL, you are now enabled to use EL for and in Dart, too.And No, it is not.EL indeed is more of a specification than an implementation. You can see it as a light weight scripting mechanism allowing you to easily access application logic and data with simple expression. You can see it as a templating engine that helps you generate proper text format of your choice. You can hook it with your presentation layer and do things similar to JSP pages. Or you can even use it to establish the whole data binding system that support MVVM design patterns.Use Rikulo ELRikulo EL implements the EL specification thus you can use it as what you have used it before if you are familiar with it. Or maybe you want to check the EL specificationn for details.Nevertheless, I will show you the enhancements that Rikulo EL added that are specific for Dart language.Access variablesFollowing is a typical "Hello World" example. The variable to be evaluated is provided by use of VariableMapper.import 'dart:mirrors' show reflect;
import 'package:rikulo_el/el.dart';
class Person {
String name;
Person(this.name);
}
void main() {
//Prepare an expression factory.
ExpressionFactory ef = new ExpressionFactory();
//Prepare the expression script
//expression inside #{...} is to be evaluated
String script = 'Hello, #{person.name}!';
//Prepare an expression context.
ELContext ctx = new ELContext(
resolveVariable:
(String name) => name == 'person' ? new Person('Rikulo'): null);
//Parse the script and create a value expression which expect a String type
ValueExpression ve = ef.createValueExpression(ctx, script, reflect('').type);
//Evaluate the expression and return the evaluated result
print(ve.getValue(ctx)); //'Hello, Rikulo!'
}
Instead of reflecting the string's type (with reflect()), you can use STRING_MIRROR instead.Access functionsFollowing is still a typical "Hello World" example. Here we use FunctionMapper.import 'dart:mirrors' show reflect;
import 'package:rikulo_el/el.dart';
class Person {
String name;
Person(this.name);
}
void main() {
//Prepare an expression factory.
ExpressionFactory ef = new ExpressionFactory();
//Prepare the expression script
//expression inside #{...} is to be evaluated
String script = 'Hello, #{currentPerson().name}!';
//Prepare an expression context.
Person currentPerson() => new Person('Rikulo');
ELContext ctx = new ELContext(
resolveFunction:
(String name) => name == "currentPerson" ? currentPerson: null);
//Parse the script and create a value expression which expect a String type
ValueExpression ve = ef.createValueExpression(ctx, script, reflect('').type);
//Evaluate the expression and return the evaluated result
print(ve.getValue(ctx)); //'Hello, Rikulo!'
}
Allow using Dart array syntax in EL expressionThere is no counter part in EL specification and Rikulo EL enhances the parser and evaluator to handle the Dart arrays. Following is a simple example.import 'dart:mirrors' show reflect;
import 'package:rikulo_el/el.dart';
class Person {
String name;
Person(this.name);
}
void main() {
//Prepare an expression factory.
ExpressionFactory ef = new ExpressionFactory();
//Prepare the expression script
//expression inside #{...} is to be evaluated
String script = 'Hello, #{[henri, john, mary][0].name}!';
//Prepare an expression context.
Person getPerson(String name) {
switch (name) {
case 'henri':
return new Person('Henri');
case 'john':
return new Person('John');
case 'mary':
return new Person('Mary');
}
}
ELContext ctx = new ELContext(resolveVariable: getPerson);
//Parse the script and create a value expression which expect a String type
ValueExpression ve = ef.createValueExpression(ctx, script, reflect('').type);
//Evaluate the expression and return the evaluated result
print(ve.getValue(ctx)); //'Hello, Henri!'
}
Note that such Dart array instance is created everytime the value expression is evaluated and its life scope is only within that "Evaluation". That is, after the evaluation is done, it will be left as is and finally garbage collected.Allow using Dart map syntax in EL expressionimport 'dart:mirrors' show reflect;
import 'package:rikulo_el/el.dart';
class Person {
String name;
Person(this.name);
}
void main() {
//Prepare an expression factory.
ExpressionFactory ef = new ExpressionFactory();
//Prepare the expression script
//expression inside #{...} is to be evaluated
String script =
"Hello, #{{'henri' : henri, 'john' : john, 'mary' : mary}['henri'].name}!";
//Prepare an expression context.
Person getPerson(String name) {
switch (name) {
case 'henri':
return new Person('Henri');
case 'john':
return new Person('John');
case 'mary':
return new Person('Mary');
}
}
ELContext ctx = new ELContext(resolveVariable: getPerson);
//Parse the script and create a value expression which expect a String type
ValueExpression ve = ef.createValueExpression(ctx, script, reflect('').type);
//Evaluate the expression and return the evaluated result
print(ve.getValue(ctx)); //'Hello, Henri!'
}
Note that such Dart map instance is created everytime the value expression is evaluated and its life scope is only within that "Evaluation". That is, after the evaluation is done, it will be left as is and finally garbage collected.ConclusionRikulo EL implements the Unified Expression Language specification and adds some enhancement features specific for Dart language. Authoring the presentation layer(web pages) in Dart and Rikulo will be easier and more versatile. It will serve as the important base templating engine for Rikulo UXL UI eXtensible Language and the Rikulo ORM libraries. Stay tuned.