For the current project at work, we are creating quite a few custom controls that all share the same properties and that are bindable.
#bindable required: boolean = false;
#bindable minLength: number = 0;
#bindable maxLength: number = 0;
Since we'd like to avoid code duplication, the idea is to keep these bindable properties in a separate class, called 'Validation' in this case.
import {Validation} from "./validation";
export class MyClass {
private validation: Validation = new Validation();
// also tried:
// #bindable validation: Validation = new Validation();
}
The question is how to get the HTML to bind to the properties in the Validation class. Doing this validation.required.bind="someProperty.required" doesn't update the required property on the validation instance. We attempted to use DI, but that didn't seem to cut it either.
import {inject} from "aurelia-framework";
import {Validation} from "./validation";
#inject(Validation)
export class MyClass {
constructor(private validation: Validation) {
this.validation = validation;
}
}
Any hints would be greatly appreciated.
EDIT:
It seems that Aurelia interprets 'validation.required' as a command rather than an expression.
WARN [templating-binding] Unknown binding command. Object {defaultBindingMode: null, attrName: "validation", attrValue: "true", command: "required", expression: null}
As a work-around until inheritance with bindable properties gets supported in Aurelia, I am binding to a class that has some of the shared properties. The bindable ones will get duplicated across the controls for now.
import {bindable, bindingMode} from "aurelia-framework";
import {IControlBase, ControlBase} from "./controlbase";
export class MyClass {
#bindable controlbase: IControlBase = new ControlBase();
#bindable label: string = "";
#bindable editing: boolean = false;
#bindable({ defaultBindingMode: bindingMode.twoWay })
value: string;
}
Related
my component have changeDetection: ChangeDetectionStrategy.OnPush and component have a array variable
myids:Array<number>;
addId(id:number){
this.myids.push(id)
}
in the template I am using:
<div [class.active]="myids.includes(step.id)"></div>
My question, is it a performance problem to use myids.includes in template ?
Yes it is an performance issue. Everytime the template must be rerendered, this array iteration must be run, also. It's a good choice to run with changeDetectionStragy.OnPush, which minimizes the amount of template rerendering.
Good practice:
You should seperate html templates which are responsible for viewing and the code of your component which are responsible to react of events and bring the model to the view.
The core concept of that is Model-View-Controller. (MVC)
I recommend to calculate your "active" property in the controller or a service.
This property is calculated only one time and can easily bound to your template.
Do it like this:
public class MyComponent {
public isActive: boolean;
private myIds: string[];
constructor() {
this.isActive = false;
this.myIds = [];
}
public ngOnInit(): void {
// load myIds
// this.myIds = this._myIdsService.getIds();
this.isActive = this._myids.includes(step.id);
}
}
And then bind this property to your view...
<div [class.active]="isActive"></div>
In Spring when a controller method is annotated with #JsonView, it returns only the
respective annotated properties of the object honoring the configuration
spring.jackson.mapper.default-view-inclusion, which is set to false by default.
// Kotlin code
abstract class Base {
lateinit var transientInternalProperty: String
}
class Main(val externalProperty: String) : Base()
#RestController
#RequestMapping("/")
class MainController {
#JsonView(Views.Public::class)
#GetMapping("/")
fun index() = Main()
}
Taking the above example, how to exclude non annotated properties on the generated
Main_Public schema. How to leave transientInternalProperty out of Main_Public without having to annotate it also?
I couldn't find anything about this in the documentation. Just this small section.
I tried to annotate the class itself with #JsonView to indicate "default view" for properties but it did not work.
To exclude properties from the generated OpenAPI sepc: prefer swagger-annotation, you #Hidden or #Schema(hidden = true)).
I have a class of type A.
This class has several properties, let's call them prop1, prop2 and prop3.
When I'm calling an API, that returns a JSON string representing the object, some properties might be omitted if they are null. Further down the road, however, this object is used to construct a form dynamically (using Formik, but that's unrelated).
This framework expects all properties to be there, and some will be visible dynamically depending on other properties.
So my question, how can I parse a JSON response to my custom class, keeping default values in case properties are omitted in the API response?
What I've tried was:
static getCustomer(id) {
return fetch(process.env.MD_API_URL + 'customers/' + id, { mode: 'cors' })
.then(response => {
let cust = new Customer();
return response.json().then(x => cust = JSON.parse(x));
}).catch(error => {
return error;
});
}
But this returns undefined. Must be doing something wrong...
since typescript is not actually compiled but translated into javascript so all the javascript rules apply.
Therefore deserializing json wont actually create a new instance of the class in question but gives you an object you can "call" Customer during design time.
you could however create an object and then assign the json values like this:
export class Customer {
public id: number;
public name: string;
// your stuff here
public myDefaultProp: string = "default value";
public constructor(init?: Partial<Customer>) {
Object.assign(this, init);
}
}
your return then would look like this:
return response.json().then(x => new Customer(JSON.parse(x)));
added an example https://stackblitz.com/edit/typescript-16wlmg
This essentially just a matter of determining what to do in order to create an instance of a class, and map the properties of a JSON response towards your custom class, and there could be many different ways to solve this,
But I think (Factory function) is appropriate approach for this kind of task.
We are stuck with a issue where we have a non abstract parent class with 2 sub classes as shown below. When type information is provided the default deserialization process of Jackson works fine. But when no information is provided as the request object is of base class; the deserilization process gets fail.
#JsonTypeName("Vehicle")
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type"
)
#JsonSubTypes({
#Type(value = Car.class),
#Type(value = Bicycle.class)
})
class Vehicle{
int number;
}
#JsonTypeName("Car")
class Car extends Vehicle{
int seatingCapacity;
}
#JsonTypeName("Bicycle")
class Bicycle extends Vehicle{
String handleType;
}
The following request works fine:
{
"type" : "Car",
"number": "1244"
"seatingCapacity": 2
}
But the following request fails:
{
"number": "2222"
}
Our expectation is that if type information is missing than the last json request should get deserialized to base class i.e. Vehicle.
Could you please help us with this? Thanks !
Using spring-boot-starter-web:1.5.2.RELEASE
You should update your JsonTypeInfo
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type",
defaultImpl = Car.class
)
Also, use the latest version of Jackson dependency
Hope It's work.
I would like to develop some of the webcomponents in a Polymer 2.0 project with scala.js. While there is a wonderful demo-project on github demonstrating how it works with Polymer 1.0. I cannot get something similar to work with Polymer 2.0 and the native Element-registration technique.
A simple facade might look like the following
#ScalaJSDefined
class PolymerElement extends PolymerBase {
def is: String = ""
def properties: js.Dynamic = js.Dynamic.literal()
}
#js.native
#JSGlobal("Polymer.Element")
class PolymerBase extends HTMLElement
The actual Element:
#JSExportTopLevel("MyElement")
#ScalaJSDefined
class MyElement extends PolymerElement {
private var label = "init"
override def is = "my-element"
override def properties = js.Dynamic.literal(
"label" -> Map(
"type" -> "String",
"value" -> "init",
"notify" -> true
).toJSDictionary
)
def testMe = {
println(label)
}
}
object MyElement {
#JSExportStatic
val is: String = MyElement.is
#JSExportStatic
val properties: js.Dynamic = MyElement.properties
}
No matter whether I take the old style element registration Polymer(MyElement) or the platform native variant window.customElement.define(MyElement.is, MyElement)
It obviously throws an exception as MyElement isn't instatiable with new MyElement.
It throws the exception:
Uncaught TypeError: Class constructor PolymerElement cannot be invoked without 'new'
Studying the Scala.js facade writing guide, I already tried a lot of facade variants declaring PolymerElement and PolymerBase abstract.
A possible solution that comes to my mind is, writing a native JavaScript Class, that indeed is instantiable and using #js.native facades on them. But I'm looking for a way to achieve it with something Scala.js 0.6.16 provides.
Updated version (2018-04)
Ok, this is possible helps to someone else too and I decided to publish my new version of it.
I'm using this pure ScalaJS solution to integrate with Polymer2/CustomElements.
My environment is:
Scala : 2.12
ScalaJS: 0.6.22
And also : "org.scala-js" %%% "scalajs-dom" % "0.9.2"
ScalaJS options:
"-P:scalajs:sjsDefinedByDefault"
I've created some ScalaJS facades for CustomElements and Polymer 2 and published them here - https://bitbucket.org/latestbit/scalymer/src/tip/src/main/scala/org/latestbit/sjs/polymer2/?at=default
They're not full-featured Polymer facades, just in the very beginning state, but they are working for me.
And you can use them easily without any hacks like:
#JSExportTopLevel(name = "TestElement")
class TestElement() extends Polymer.Element {
override def connectedCallback(): Unit = {
super.connectedCallback()
global.console.log(s"Attribute name ${getAttribute("name")}. Body is ${dom.document.querySelector("body")}")
global.console.log(s"${this.$.selectDynamic("testCl")}")
global.console.log(s"${$$("testCl")}")
}
}
object TestElement {
#JSExportStatic
def is = "test-element"
#JSExportStatic
def properties = js.Dictionary(
"name" -> js.Dictionary(
"type" -> "String"
)
)
}
Then register it also in Scala like:
object TestJsApplication {
def main() : Unit = {
Globals.customElements.define(TestElement.is,
js.constructorOf[TestElement]
)
}
}
The html part is usual:
<dom-module id="test-element">
<template>
<span id="testCl">Not much here yet.</span>
This is <b>[[name]]</b>.
</template>
</dom-module>
You will find the complete example here - https://bitbucket.org/latestbit/scalymer/src
An old try to solve (for historical purposes)
Ok, this is the best 'solution' I've found.
This is not solving it completely, but I hope it'll be a helpful trick while we're expecting sjs improvements in this area.
Get any library to 'mixin' js classes. I've used https://github.com/rse/aggregation.
Create your ScalaJS component but don't try to inherit it from Polymer.Element directly:
#ScalaJSDefined
#JSExportTopLevel("TestPolymerElement")
class TestPolymerElement extends js.Object {
def test = g.console.log("Hello from scala")
}
object TestPolymerElement {
#JSExportStatic
def is = "test-polymer-element"
}
Create a JS pure "companion" class to inherit Polymer.Element and ScalaJS component as a mixin and register it:
class TestPolymerElementJs extends aggregation(Polymer.Element,TestPolymerElement) {
}
customElements.define(TestPolymerElementJs.is, TestPolymerElementJs);
Also, you can define the properties and manage them in ScalaJS like:
#ScalaJSDefined
#JSExportTopLevel("TestPolymerElement")
class TestPolymerElement(val name : String) extends js.Object {
def test = g.console.log(s"Hello from ${name}")
}
object TestPolymerElement {
#JSExportStatic
def is = "test-polymer-element"
#JSExportStatic
def properties = js.Dictionary (
"name" -> js.Dictionary(
"type" -> "String"
)
)
}