Custom Attribute on Aurelia not working - aurelia

I am a beginner by Aurelia. I want to program a Custom Attribute as you see here:
square.js:
/*jshint esversion: 6 */
import {bindable, inject} from 'aurelia-framework';
#inject(Element)
export class SquareCustomAttribute {
#bindable sideLength;
#bindable color;
constructor(element){
this.element = element;
}
sideLengthChanged(newValue, oldValue){
this.element.style.width = this.element.style.height = `${newValue}px`;
}
colorChanged(newValue, oldValue){
this.element.style.backgroundColor = newValue;
}
}
and you can see html in the following:
<template>
<require from="./square"></require>
<div square="color.bind: squareColor; side-length.bind: squareSize"></div>
</template>
I get an error:
ERROR [app-router] Error: (SystemJS) Unable to dynamically transpile ES module as SystemJS.transpiler set to false.
Could you please help me?

An easy way to do what you are trying to do (not purely an attribute) is this:
try this:
square.html
<template bindable="sideLength, color">
<div css.bind="height: ${sideLength}; width: ${sideLength}; background-color: ${color}"/>
</template>
now you just use it like this:
[any].html
<require from="[path]/[to]/square.html"></require>
.
.
.
<square side-length="50" color="red"></square>
.
.
.
There is almost an exact example of this under data binding in the docs:
Aurelia Docs: Cheat Sheet - Databinding

Creating an answer so this can be closed.
User had an error with his script file causing the transpiler to fail. Changing the file extension from .js to .ts solved the issue as the TypeScript file could be handled by SystemJS.

Related

importing components in ngx-bootstrap throws 'not a known element' error

I imported the datepicker and it shows up fine.
But when I try to import a typeahead or buttons or anything, I get the <whatever> is not a known element error.
What I'm doing is import the module in the app.module like that:
import {DatepickerModule} from 'ngx-bootstrap/datepicker';
import { TypeaheadModule } from 'ngx-bootstrap/typeahead';
import { ButtonsModule } from 'ngx-bootstrap/buttons';
// also tried:
// import { DatepickerModule, TypeaheadModule... } from 'ngx-bootstrap';
// ..but again no luck
...
imports: [
DatepickerModule.forRoot(), //only this works
TypeaheadModule.forRoot(),
ButtonsModule.forRoot(),
...]
Then on my history.module in a same way with the only difference that .forRoot() is now omitted.
Then on a child component of the parent history component I have:
<span *ngIf="showFilters" class="value bootstrap-iso" >
<div style="display:inline-block;">
<datepicker
[(ngModel)]="dt"
[datepickerMode]="'month'"
[showWeeks]="false"
[dateDisabled]="dateDisabled"
[maxDate]="today">
</datepicker>
</div>
</span>
which works, but for example these don't work:
<typeahead [typeahead]="'documents'"></typeahead>
<btnCheckbox></btnCheckbox>
Doesn't matter if I include ngModel or other attributes, I always get the not a known element error. So I assume it has to do with my imports, my naming, or somethng, but honestly I can't see what's missing.
EDIT: Using Angular 4, "#angular/cli": "1.1.1", "ngx-bootstrap": "^1.7.1", "bootstrap": "^4.0.0-alpha.6", "typescript": "~2.3.3"
Well, I actually have to add the input shown in the template section in the documentation.
So this works:
<input [(ngModel)]="selected"
[typeahead]="documents"
class="form-control">
Because the documentation mentions Selector and Exported as I thought we should use these values. I thought the templates are just showing how the components work under the hood.
As my collegue said , please add
import {FormsModule, ReactiveFormsModule} from '#angular/forms';

Error when trying to load a my Aurelia custom element

I am a newbie with Aurelia and I am trying to create my first custom element. I am coming from Angular 1 and as far as I could understand, custom elements seems to be similar to Angular 1 directives.
So, I am getting the following error:
I have checked my template looking for some bad written html, but I can't find it. Does anyone have any idea? Code is shown below:
src/views/login/login.html
<template>
<require from = "/resources/elements/login-form/login-form"></require>
<h1>Login</h1>
<login-form></login-form>
</template>
src/views/login/login.js
export class Login {}
src/resource/elements/login-form/login-form.html
<template>
<div>Here's gonna be a form</div>
</template>
src/resource/elements/login-form/login-form.js
import {customElement} from 'aurelia-framework';
#customElement('login-form')
export class LoginForm {
}
src/resource/elements/login-form/login-form.js as below
export class LoginFormCustomElement {
}
This will work Aurelia framework having naming Conventions. When ever you are using as a custom element better to pass class name with end of CustomElement.

how to add and remove custom elements on the fly or by an click event in aurelia

Almost give up on Aurelia, I'm struggling with adding custom elements dynamic in Aurelia,
lets say we have a custom tag:
view my-element.html:
<template> My Element ${name} </template>
viewmodel: my-element.js:
export class MyElement {
#bindable name = '';
}
so I try to manually add this tag, in another view:
<template>
<button type="button" click.delegate="createMyElement()">Remove</button>
</template>
another viewmodel:
export class App {
createMyElement() {
//how to do it in here to create element
//<my-element name='name1'></my-element>
}
}
I looked this link https://gist.run/?id=762c00133d5d5be624f9, but it needs a container reference
<div ref="container"></div>
I dont want to specify a container, instead I want it to be append to current view.
I also tried using aurelia-compiler from https://github.com/gooy/aurelia-compiler, when I try to import it, it was able to locate file'gooy/aurelia-compiler', but I got this error:
Error invoking Compiler. Are you trying to inject/register something that doesn't exist with DI?
Can someone please help? thanks.
You could inject the view's html element and use it as a "container". Like this:
import {inject} from 'aurelia-framework';
import {ViewFactory} from './view-factory';
#inject(Element, ViewFactory)
export class App {
//...
constructor(element, viewFactory) {
this.element = element;
this.viewFactory = viewFactory
}
}
Then, use this.element in the insert method:
this.dispose = this.viewFactory.insert(this.element, this.viewHtml, viewModel);
Running example:
https://gist.run/?id=9d5e7a60cd02e55618829a304df00621
Hope this helps!
Rather than trying to manually inject views through your viewModel (controller), try creating new viewModels from which to generate views. So, like this:
home.html
<template>
<my-element repeat.for="name of names" name.bind="name"></my-element>
<button click.delegate="addName()">Create My Element</button>
</template>
home.js
export class HomeViewModel {
constructor() {
this.names = []
}
addName() {
this.names.push('Jim');
}
}

Binding multiple expressions in custom attributes

I am having trouble binding multiple expressions in Aurelia custom attributes. I am posting this because I have been struggling and I believe that the documentation might be missing something (?). Hopefully it is not some stupid thing that I missed so that more people will have use of this aswell.
This is my simplified implementation.
resultCustomAttribute.js
import {inject, bindable} from 'aurelia-framework';
#inject(Element)
export class resultCustomAttribute {
#bindable foo;
#bindable bar;
constructor(element) {
this.element = element;
console.log(this.foo); // => null
console.log(this.bar); // => null
}
fooChanged(value){
console.log(value) // Does not run
}
}
main.js
export function configure(aurelia) {
aurelia.use
.standardConfiguration()
.developmentLogging()
.feature('resources'); // resources is a folder in the source root
with an index.js file that sets my custom
attribute as a globalResource
aurelia.start().then(a => a.setRoot());
}
home.html
<template>
.
.
.
<div repeat.for="item of items"> <!-- items is an array of objects in home.js-->
<h4>${item.title}</h4>
<div result="foo.bind: item.foo; bar.bind: item.bar">
...
</div>
</div>
.
.
.
</template>
The problem is that whatever I bind foo and bar too, they become null in my custom attribute. the element is however passed to the resultCustomAttribute correctly. Is my implementation correct or am I missing something?
EDIT: The above implementation seems to be correct after all. When I simplified my code to provide a general purpose question, I removed the camelCase named variable selectionIndex and replaced it with bar as seen above. This caused the selectionIndexChanged function not to run.
And the reson that this.foo and this.bar are null in the contructor is simply because the constructor is run before the values are changed for the first time.
This is a bit embarrasing. After asking this question suddenly the foo variable started to work, and I couldn't find how to reproduce my original problem. fooChanged ran correctly but my barChanged still did not run at all.
This is because the barvariable is not actually named bar in my real code, It is a variable with camelCase naming selectionIndex. When using camelCase naming aurelia did not hook my selectionIndexChanged correctly. I changed it to selectionindex and selectionindexChanged and now both variables are bound as they should.
Sorry for waste of space. But maybe this will be useful for someone.
EDIT
see comment by shunty for explanation on how to use camelCase in custom attributes

aurelia: Custom defined VM in your VM

Hi I am looking for a way to probarly add new VM objects in my current VM
Can anyone help me how to do this?
The idea is that this should output
Hi!
my name is jhonny
Code i have so far
import {foo} from 'dist/foo';
export class Main{
constructor(){
this.heading = "hi!"
this.fooVar = new Foo("jhonny");
}
}
<template>
<section>
<h2>${heading}</h2>
<import from="./foo"></import>
<foo item.bind="fooVar"></foo>
</section>
</template>
export class Foo{
static Behavior(){
return Behavior
.customElement('foo');
}
constructor(name){
this.name = name;
}
}
<template>
<section>
<h2>my name is ${name}</h2>
</section>
</template>
Also tried
<foo item.bind="fooVar"></foo>
<foo bind="fooVar"></foo>
<foo model.bind="fooVar"></foo>
<compose
model.bind="fooVar"
view-model="foo">
</compose>
They all give "my name is" without the variable name. So i guess its not binding
I think you don't need to instantiate the Foo.
and it probably should be:
<foo name.bind="fooVar"></foo>
and
Behaviour.withProperty('name');
Your stated goal is: Add VM object in current VM. Here's the code for that (it removes the "custom element" you were adding, and uses instead a property in the main VM that is itself an object):
export class Main{
constructor(){
this.heading = "hi!"
this.fooVar = new Foo("jhonny");
}
}
<template>
<section>
<h2>${heading}</h2>
<h2>my name is ${fooVar.name}</h2>
</section>
</template>
export class Foo{
constructor(name){
this.name = name;
}
}
I created a sandbox code project to illustrate the above (it is written in TypeScript)
If you want to try out the sandbox code project, here are the instructions
I added an Aurelia TypeScript Wizard Navigation Sample to show an alternative to the approach you asked about.