Rendering views in spineJS? - spine.js

Just so you know this is my first question here on stackoverflow, so I apologize if something is wrong with my question.
OK, So I have just started using spine, it is my first delve into MVC frameworks and I am having trouble with rendering a .eco template.
It is probably something really basic but whenever i run 'hem server', all I see is a blank page?
Here is the hello.coffee controller:
Spine = require('spine')
class Hello extends Spine.Controller
constructor: ->
super
render: ->
#html require('views/view')
module.exports = Hello
Here is views/view.eco
<h1>Hello World</h1>
And here is app/index.coffee
require('lib/setup')
Spine = require('spine')
Hello = require('controllers/hello')
class App extends Spine.Controller
constructor: ->
super
#hello = new Hello
#append #hello
module.exports = App
When I visit the app with the JS console open no errors are produced and if I vist localhost:9294/test everything is ok?
Thanks in advance to anyone can help me and my noobiness! ;)

you can also have your controller constructor method call the render for you:
class Hello extends Spine.Controller
constructor: ->
super
#render()
render: ->
#html require('views/view')

Related

How to use ionViewDidEnter in directives

I am trying to create a directive where I animate a fab-button when the view is shown.
The animation works if it is inside ngOnInit, but due to ionic route strategy the animation doesn't work when I leave the page and go back. Putting it in ionViewDidEnter didn't work because I presume that ionViewDidEnter doesn't work inside the directive. So is there any approach I can take to solve this?
<ion-fab vertical="bottom" horizontal="end" slot="fixed">
<ion-fab-button mode="md" appAnimateFab>
<ion-icon name="create" mode="md"></ion-icon>
</ion-fab-button>
</ion-fab>`
#Directive({
selector: 'ion-fab-button[appAnimateFab]'
})
export class AnimateFabDirective implements OnInit {
constructor(
private animationBuilder: AnimationBuilder,
private element: ElementRef
) { }
ngOnInit() {
}
ionViewDidEnter() {
console.log(this.element);
const factory = this.animationBuilder.build([
style({transform: 'rotate(-45deg)'}),
animate('5s ease-in', style({transform: 'rotate(0deg)'}))
]);
const anim = factory.create(this.element.nativeElement);
anim.play();
}
}
This is an interesting question. I got halfway through writing out a detailed reply yesterday when I realised that you were actually asking about directives and not custom components... so all my research was wrong haha.
Today I have had another look. The tutorials all seem to conveniently miss having a requirement to deal with pages changing backwards and forwards and just lean on ngOnInit.
After scratching my head for a bit I started to wonder how else it could be triggered and I'm thinking: what about the Intersection Observer API?
I really like the way Alligator.io explain things:
Using the Intersection Observer API to Trigger Animations and Transitions
Their example shows the animation being triggered every time you scroll down to view.
If you are flipping pages then it feels like it should trigger as coming into view, but I haven't tested this out with code.
For a more Ionic-focused example with Intersection Observer API, Josh has a tutorial:
Animating List Items in Ionic with the Intersection Observer API | joshmorony - Learn Ionic & Build Mobile Apps with Web Tech
Maybe you can adapt this to use your animation code?

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.

Is there an elegant way to run some code after the template for a component is loaded in Aurelia?

I am new to ES6 and Aurelia. I would like to execute some code after a template for a component loads. What I'm trying to do is get the page down editor working inside an Aurelia component. The imports seem to work for the most part (although Sanitizer doesn't seem to be imported), but I'm not sure how to run my initialization code after the template loads.
import 'Markdown.Converter'
import 'Markdown.Sanitizer'
import 'Markdown.Editor'
export class AddProject {
constructor(){
}
}
// initialization code
var converter1 = new Markdown.Converter();//Markdown.getSanitizingConverter(); // commented out doesn't work
var editor1 = new Markdown.Editor(converter1);
editor1.run();
I just want to run my initialization code for the template after it get's loaded into the dom. Any ideas?
Use attached
export class MyClass{
attached(){
alert('My template is attached');
}
}

Using humane.js with aurelia

I'm trying to use humane.js with aurelia however I'm running in a problem.
It appears humane.js adds an element to the DOM when it's created and so far the only way I've found to do it is to force it like this....
showMessage(message) {
this.notify = humane.create();
this.notify.log(message);
}
However this creates a new instance of humane every time showMessage() is called. This breaks the queue as each one is rendered separately.
I've tried putting the create() in the activate() method of the view model but that doesn't seem to work either.
Any ideas?
This solved the problem, I've created a custom element for humane that is then included in app.html in the same way loading-indicator is in the skeleton app.
import humane from 'humane-js';
import 'humane-js/themes/original.css!';
import {inject, noView} from 'aurelia-framework';
import { EventAggregator } from 'aurelia-event-aggregator';
import { ApiStatus } from 'resources/messages';
#noView
#inject(EventAggregator)
export class StatusIndicator {
constructor(ea) {
this.ea = ea;
ea.subscribe(ApiStatus, msg => this.showMessage(msg.apistatus));
}
attached() {
this.humane = humane.create();
}
showMessage(message) {
this.humane.log(message);
}
}
The important part was the attached() this allows the setup of humane to work correctly.
Unfortunately for Aurelia, Humane will attach itself to the DOM automatically as a child of body, which Aurelia then replaces.
There is a really, really, simple fix for this:
Change your:
<body aurelia-app="main">
To this:
<body><div aurelia-app="main">
This way, Aurelia doesn't replace the div which is in body, you don't need to worry about attached() or where the import appears in your code, and humane works perfectly.
I have raised a humane github issue for this. https://github.com/wavded/humane-js/issues/69
Here is how I am using humane.js with Aurelia:
1) I load the CSS in the app index.html.
2) In each view model that requires humane, I import humane
import humane from 'humane-js/humane';
I do NOT inject human into the view model.
3) I show notifications like this:
humane.log('Error:, { addnCls: 'humane-libnotify-error' });
I hope this helps you.

Spine.js rendering view

I've just started using spine and I'm having trouble understanding a few things...
class Spk.Register extends Spine.Controller
render: ->
#html("<h1>Registration!</h1>")
...
Zepto(function($) {
new Spk.Register({
el: $("#data")
});
});
...I was expecting this to replace any html in the #data element with the html passed to #html when the controller is instantiated, but it doesn't, nothing happens at all.
I've also tried putting the render method in the constructor function but again nothing happens.
How would I replace the html in body with given html when the controller is instantiated?
The problem is the render() method isn't called.
You have to call it explicitly after controller instantiated.
Anyway, I think you shouldn't do any rendering in the constructor.
Better option is:
to have a model (MVC architecture) which triggers particular event
after the data loaded from the server,
the controller should define event handler for that event and it will render the view.
EDIT
Just very simple code snippet how it could be (CoffeeScript, using jQuery):
The Task model class:
class Task extends Spine.Model
#configure 'Task', 'name', 'deadline'
#fetch () ->
Task.deleteAll()
# ... load data from the server ...
Task.create name: 'foo', deadline: '2012-11-22' # create local instance(s)
Task.trigger 'data-loaded'
return
The controller:
class Tasks extends Spine.Controller
constructor: ->
super
init: () ->
#routes
'list': (params) ->
Task.fetch()
return
Task.bind 'data-loaded', () =>
#render()
return
return
render: () ->
#el.render Task.all()
return
The initialization code (another possibility could be Spine.js controller stack):
tasksCtrl = new Tasks el: $('.task-list')
tasksCtrl.navigate 'list'
Note that it requires also route.js (included in Spine.js) and I've used Transparency template engine (it's #el.render() meth). Then the template looks like:
<div class="task-list">
<div class="task">
<span data-bind="name"></span>
<span data-bind="deadline"></span>
</div>
</div>