Git Product home page Git Product logo

ui's Introduction

Space Brand Mood

SPACE Circle CI Join the chat at https://gitter.im/meteor-space/general

Modular application architecture for Meteor, with following goals:

  1. Explicit dependencies in your code
  2. Full control over configuration and initialization
  3. Testability

Why?

As your Meteor app grows, you keep adding packages and dependencies to it and sprinkle your configuration and initialization logic into Meteor.startup blocks all over the code base. If you don't use some structure, you will end up throwing your laptop against the wall.

1. Explicit Dependencies

Space comes with a lightweight dependency injection system. It tries to keep your code as clean as possible and doesn't force you to wrap your functions with library calls.

If an object needs other code during runtime, it simply declares its dependencies:

var dependentObject = {
  dependencies: {
    lib: 'OtherCode'
  },
  sayHello: function() {
    this.lib.sayHello();
  }
};

Now dependentObject declares very explicitly that it needs OtherCode which it will access via this.lib later on. But where does OtherCode come from?

This is where the Space.Injector helps out:

var library = { sayHello: function() { console.log('hello!'); } };
var injector = new Space.Injector();

// maps the string identifier 'OtherCode' to the library object
injector.map('OtherCode').to(library);
// injects all dependencies into the dependent object
injector.injectInto(dependentObject);

dependentObject.sayHello(); // logs: 'hello!'

Of course, this also works with Javascript constructors and prototypes:

var MyClass = function() {};
MyClass.prototype.dependencies = { lib: 'OtherCode' };
MyClass.prototype.sayHello = function() { this.lib.sayHello() };

var instance = new MyClass();
injector.injectInto(instance);
instance.sayHello(); // logs: 'hello!'

This was just first glimpse into dependency injection, there many other ways to map your code and you can add your own too:

Learn more about Space.Injector

Sidebar: Namespaces and Classes

In the examples above we used plain Javascript, but Space comes bundled with a simple but powerful inheritance system with namespacing and classes:

var myApp = Space.namespace('myApp');

Space.Object.extend('myApp.MyBaseClass', {
  dependencies: { lib: 'OtherCode' },
  sayHello: function() { this.lib.sayHello(); }
});

MyBaseClass.extend('myApp.MySubClass', {
  name: '',
  sayHello: function() {
    myApp.MyBaseClass.prototype.sayHello.call(this);
    console.log('I am ' + this.name);
  }
});

var instance = myApp.MySubClass.create({ name: 'Dominik' });
injector.injectInto(instance);
instance.sayHello(); // logs: 'hello!' and 'I am Dominik'

This was just the very basic example, there are many other features that help you build awesome classes with Space:

Learn more about Space.Object

2. Control over configuration and Initialization

Ok, now you declared your dependencies and learned how to inject them. The next questions is: "Where should the mapping of string identifiers to actual implementations happen?".

Applications

Applications are the command center of your code. Here you configure and initialize all the different pieces:

var App = Space.Application.extend({
  // This is automatically called on creation
  configure: function () {
    // every app has its own injector by default
    this.injector.map('ExternalLib').to(SomeLibrary);
    this.injector.map('MyDependentClass').toSingleton(MyClass);
  },
  startup: function() {
    // Create the singleton instance of my class
    this.injector.create('MyDependentClass');
  }
});

app = new App()
app.start(); // You decide when your app starts

because singletons are needed so often, there is even a much shorter way to express the above:

var app = Space.Application.create({
  // Let the framework map and create the singleton instances for you
  singletons: ['MyDependentClass', 'MyOtherSingleton']
});
app.start(); // You decide when your app starts

Modules

When your application grows, it will become tedious to setup everything in your main application. It's time to split up your code into modules!

Modules work exactly like applications, in fact Space.Application inherits from Space.Module. However they don't create an injector for themselves, but use the one provided by the (single) application. This way, all modules within your app share the same injector.

Modules declare which other modules they require and what runtime dependencies they have, by putting the special properties requiredModules and dependencies on their prototypes:

var MyModule = Space.Module.define('MyModule', {
  // Declare which other Space modules are require
  requiredModules: [
    'OtherModule',
    'YetAnotherModule'
  ],
  // Declare injected runtime dependencies
  dependencies: {
    someService: 'OtherModule.SomeService',
    anotherService: 'YetAnotherModule.AnotherService'
  },
  // This method is called by the Space framework after all
  // required modules are initialized and the dependencies
  // are resolved and injected into the instance of this module.
  onInitialize: function() {
    // Add mappings to the shared dependency injection system
    this.injector.map('MyModule.TestValue').to('test');
    // Use required dependencies
    this.someService.doSomeMagic()
    this.anotherService.beAwesome()
  }
});

Creating Applications based on Modules

Space.Application.create({
  // Applications also declare which modules they need:
  requiredModules: ['MyModule'],
  // And their runtime dependencies from required modules:
  dependencies: {
    testValue: 'MyModule.TestValue'
  },
  // This is called when all required modules are configured.
  afterInitialize: function() {
    console.log(this.testValue); // logs 'test' (see module above)
  }
})

Configuring Modules and Applications

You can define default configurations for each module and application and override any part of it when creating an application instance like here:

Space.Module.define('FirstModule', {
  configuration: {
    firstToChange: 'first',
    firstToKeep: 'first'
  }
});

Space.Module.define('SecondModule', {
  requiredModules: ['FirstModule'],
  configuration: {
    secondToChange: 'second',
    secondToKeep: 'second'
  }
});

TestApp = Space.Application.extend({
  requiredModules: ['SecondModule'],
  configuration: {
    appConfigToChange: 'app',
    appConfigToKeep: 'app'
  }
});

var app = new TestApp({
  configuration: {
    firstToChange: 'firstChanged',
    secondToChange: 'secondChanged',
    appConfigToChange: 'appChanged'
  }
});

expect(app.injector.get('configuration')).to.deep.equal({
  firstToChange: 'firstChanged',
  firstToKeep: 'first',
  secondToChange: 'secondChanged',
  secondToKeep: 'second',
  appConfigToChange: 'appChanged',
  appConfigToKeep: 'app'
});

3. Testability

You may ask why you should deal with dependency injection if you can access your dependencies directly like this:

var Customer = function(id) {
  this.id = id;
};

Customer.prototype.getPurchases = function() {
  return Purchases.find({ customerId: this.id }).fetch();
}

This works well, until you write your first unit tests. The problem is that this class directly references Purchases and there is only one way you can test this (sanely):

By temporarily replacing Purchases globally with some mock/stub

describe('Customer.getPurchases', function() {

  beforeEach(function() {
    // Save a backup of the global Purchases collection
    this.savedPurchasesCollection = Purchases;
    // Replace the collection with an anonymous one
    Purchases = new Mongo.Collection(null);
    this.customerId = 'xyz';
  })

  afterEach(function() {
    // Restore the global purchases collection
    Purchases = this.savedPurchasesCollection;
  })

  it('queries the purchases collection and returns fetched results', function() {
    // Prepare
    var testPurchase = { _id: '123', customerId: this.customerId };
    Purchases.insert(testPurchase);
    // Test
    var customer = new Customer(this.customerId);
    var purchases = customer.getPurchases();
    expect(purchases).to.deep.equal([testPurchase]);
  })
})

In this example it does not look too bad but this pattern quickly becomes tedious if you have more than 1-2 dependencies you want to replace during your tests.

Here is how you can write a test like this when using space:

var Customer = Space.Object.extend({
  // Annotate your dependencies
  dependencies: { purchases: 'Purchases' },
  id: null,
  getPurchases: function() {
    this.purchases.find({ customerId: this.id }).fetch();
  }
});

describe('Customer.getPurchases', function() {

  beforeEach(function() {
    this.customerId = 'xyz';
    // Inject dependencies directly on creation
    this.customer = new Customer({
      id: this.customerId,
      purchases: new Mongo.Collection(null) // dependency
    });
  })

  it 'queries the purchases collection and returns fetched results', function() {
    // Prepare
    testPurchase = { _id: '123', customerId: this.customerId };
    this.customer.purchases.insert(testPurchase);
    // Test
    var purchases = customer.getPurchases();
    expect(purchases).to.deep.equal([testPurchase]);
  })
})

Since the dependencies property is just a simple prototype annotation that has no meaning outside the Space framework, you can just inject the dependencies yourself during the tests. This pattern works great, because your code remains completely framework agnostic (you could replace Space by any other DI framework or do it yourself). The positive side effect is that you explicitely declare your dependencies now. This helps you keep an eye on the complexity and coupling. If you realize that a class has more than 5 dependencies, it might be a good i ndicator that it is doing too much.

Further Examples

Look through the tests of this package to see all features that space:base provides for you.

Migration Guide

3.2.1 → 4.0.0

The 4.0.0 release has brought many small breaking changes and improvements.

Lowercase API properties

All api properties, significant to the framework are now like "normal" properties:

Space.Module.define('My.CustomModule', {
  requiredModules: ['My.OtherModule'], // instead of RequiredModules
  singletons: ['My.OtherModule'], // instead of Singletons
})
Space.Object.extend('My.CustomClass', {
  dependencies: { /* … */ } // instead of Dependencies
})

Module Lifecycle Changes

Previous hooks like onStart and onConfigure have been replaced with a complete lifecycle split into three main phases: initialize, start, reset. Each with on, before and after hooks like onInitialize / afterStart etc.

Space.Module.define('My.CustomModule', {
  onInitialize() {} // instead of "onConfigure"
  onStart() {} // same as previous "onStart"
  onReset() {} // did not exist before -> hook to reset collections etc.
})

New Class Registry

There is a new recommended way to define classes with full class path for improved debugging and automatic type registration (EJSON / toData):

// Instead of:
Space.Object.extend(My.namespace, 'MyCustomClass');
// Do this now:
Space.Object.extend('My.namespace.MyCustomClass');

Install

meteor add space:base

Run the tests

./test.sh

Release History

You find all release changes in the changelog

License

Licensed under the MIT license.

ui's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ui's Issues

Routing question

How would one go about rendering a route at a particular point in a template?

In the todo-mvc example the route is rendered at the bottom of the body. I'd like to render the route at a certain part in the template.

i.e.

<body>

  {{>menu}}
  {{>sidebar}}

  <div class="content">
    {{>view}}
 </div>

</body>

where the template corresponding to the route I'm traversing to is rendered in view. The idea here is I want view to be an area where I can display content from different modules based on routes.

So /dashboard would render the main template for the dashboard module in the view area....

How to manage a dynamic subscription based on user input

I've currently got a template manager (helpers/events/created callback) with too many concerns, and am looking for advice on how you would implement this using Space UI. This is a custom search feature of Mongo.collection documents that uses a Meteor.subscription inside the template's created callback with ReactiveVars to manage state. I have an autorun wrapping the Meteor.subscribe call so that changes to the ReactiveVar cause the subscription to rerun, and the new data to be published from the server that represents the search results.

In my refactor I plan to have:

  • a template event calls a mediator method that takes the user input
  • this sets the ReactiveVar and publishes an event
  • the store hears the event and updates the filter of the data in a similar way to the todos example.

What I don't have a plan for is the subscription. My gut feeling is this is something that belongs in the mediator as it's plumbing the store logic into the template. What's been your approach to this?

Modular components with space

Have you put any thought into how reusable/extendable objects could be
constructed for templates?

There's a trello issue discussing how it could be implemented (I mentioned space, trying to get
you some publicity!). I'd like some input from you on my suggested approach
and maybe any thoughts you have about how an interface like space could be
utilized to build components presently.

I'd love to be able to do this:

A space component

class App.myComponent extends space.component

# maybe a way of doing this automatically?
@namespace: App

Helpers:
  'myHelper'

myHelper ->
 # does stuff

A component that extends an existing space component

class extendedCmp extends App.myComponent

# being able to specify the namespace without actually having to prepend
# it to the class name might be nice. That way if you have a longer
namespace
# it doesn't clutter up the class definition... but maybe that's bad
design? idk..
@namespace: App

myHelper ->
 super()
 # do other stuff

And then use one of these components later like so

{{> App.extendedCmp }}

It'd probably take some hacking on blaze to get it to work, but it's a thought.

Space UI is hard to debug

Hi @DominikGuzei! I've been using Space UI for the last weeks and it is very nice. But very hard to debug.
For example, when a class defined in client.coffee don't exists or has some typo/error, no error message is sent. I'm going to look more about it, but I wanted to create the issue before to know if this subject was already discussed here or you have some good ideas about the reasons. Thanks Dominik!

Links:
https://github.com/fr0zen/SpaceUI-TodoMVC
http://spaceui-todomvc.meteor.com

Future support for version 3.x?

Can you still apply updates to 3.x that would improve the current feature set of it. Like

I think version 3.x fits my needs feature wise quiet good. But there are still some issues. Currently I know about those regarding the reactive state that I have reported separately.

Why I don't want to move to 4.x

Right now I don't want to replace the Flux architecture with the central message bus. Maybe I haven't understood the full benefits of your new space-messaging package. But I prefer using Meteor methods and check on the server side directly. For the client side I like the restrictions and the simple mental model that the Flux architecture creates and even though I don't have a big app wit Flux yet, I think the Dispatcher will make it easier to prevent mistakes regarding the event flow.

No mapping for identifier <Space.Application.Injector> was found

I tried space-ui on my codebase using a second branch and everything worked fine. I now wanted to start from scratch instead of merging the code, as I know some things I'd like to improve and restructure. However, I don't know what this error is about. I can post some of my code if it helps :)

[Error] Error: No mapping for identifier <Space.Application.Injector> was found.
    get (space_base.js, line 152)
    injectInto (space_base.js, line 163)
    injectInto (space_base.js, line 164)
    initialize (space_base.js, line 336)
    initialize (space_base.js, line 430)
    Application (space_base.js, line 426)
    Application (application.coffee.js, line 9)
    (anonymous function) (app.js, line 68)
    runStartupCallbacks (meteor.js, line 784)
    ready (meteor.js, line 786)

Space.ui.Mediator not available

When I meteor add space:ui to an existing app and run it, there is no Space.ui.Mediator available. Where can I get it from?

Callbacks

I want to insert a document and then use its callback to pass the returned id to a method. How and where would I do that? Does the dispatcher support callbacks and is that intended?

Mediator vs. Controller

Hi @DominikGuzei,

after using space-ui and getting into it I really like it and am willing to use it, great job so far!

One thing I am looking at right now is the Mediator and I have some suggestions/questions/discussing points for that.

Why not use one single Mediator for the whole app that is only for the communication between different parts of the application. You might want to look at ChaplinJS which has a very good implementation of the mediator pattern (http://chaplinjs.org/) and modular application design in general.

This way you could take the responsibility for e.g. helpers out of the mediator but put it into controllers or introduce a new component class that is responsible for the orchestration of templates. Maybe one could also use the iron-router controller which provides this kind of functionality?!

Keep up the good work!
Manuel

Mediator cannot be defined in Blaze Components template

Hi @DominikGuzei,

I'm experimenting using Blaze Components with space-ui.

Everything has been working well, except that I cannot define mediator for a template if that template is registered as Blaze Component.

Specifically, the UrlFormMediator here is not defined inside UrlForm template instances.

It looks like Blaze Components has interfered with the way mediator is initiated. Do you have any idea of a work-around?

Example does not work

Hi Dominik,

could it be that the example app is broken with the current release of meteor (1.0.3.2)?
Just checked it out and tried to start it and I get the following error:

W20150312-14:26:03.534(1)? (STDERR)           
W20150312-14:26:03.536(1)? (STDERR) /Users/ap/.meteor/packages/meteor-tool/.1.0.36.dkfy8t++os.osx.x86_64+web.browser+web.cordova/meteor-tool-os.osx.x86_64/dev_bundle/lib/node_modules/fibers/future.js:173
W20150312-14:26:03.536(1)? (STDERR)                         throw(ex);
W20150312-14:26:03.537(1)? (STDERR)                               ^
W20150312-14:26:03.537(1)? (STDERR) TypeError: Cannot read property 'Command' of undefined
W20150312-14:26:03.537(1)? (STDERR)     at shared/lib/commands.coffee:2:51
W20150312-14:26:03.537(1)? (STDERR)     at /Users/ap/Documents/workspaces/github-workspace/space-ui/examples/TodoMVC/.meteor/local/build/programs/server/app/shared/lib/commands.coffee.js:31:3
W20150312-14:26:03.537(1)? (STDERR)     at /Users/ap/Documents/workspaces/github-workspace/space-ui/examples/TodoMVC/.meteor/local/build/programs/server/boot.js:168:10
W20150312-14:26:03.537(1)? (STDERR)     at Array.forEach (native)
W20150312-14:26:03.537(1)? (STDERR)     at Function._.each._.forEach (/Users/ap/.meteor/packages/meteor-tool/.1.0.36.dkfy8t++os.osx.x86_64+web.browser+web.cordova/meteor-tool-os.osx.x86_64/dev_bundle/lib/node_modules/underscore/underscore.js:79:11)
W20150312-14:26:03.538(1)? (STDERR)     at /Users/ap/Documents/workspaces/github-workspace/space-ui/examples/TodoMVC/.meteor/local/build/programs/server/boot.js:82:5
=

Cheers,
Gerwin

Todo example blank page

I'm trying the Todo example but I just see the IronRouter default page with this error in console

Uncaught TypeError: Cannot read property 'prototype' of undefined index_route.coffee.js?d531f5c5ea20af1fc2a02c0b414363a8adf78300:3
Uncaught ReferenceError: IndexRoute is not defined 

JavaScript

It would be nice if you could provide the TodoMVC example in JavaScript. I'm still trying to find out how this concept works and if you're not used to CoffeeScript it's even harder. But the code looks really clean in ☕script :)

Another idea: Why not just take the standard todo app that comes with Meteor and convert it to space-ui? It would be nice to see the difference, wouldn't it?

this in templateRendered

I had something like this.find('#mainContent') in my Template.rendered function. When I just convert the code to coffeescript and space:ui, I would like to have the same data context. this in the mediator's templateRendered function seems to be the mediator object itself. Is this intended? Can I access the "normal" context somehow? This might be the same for other functions on the template.

getState and setState

I'm a bit lost again :) I have no idea why this code doesn't work now, it aready did on my other branch -.-

Some code:

class App.CasesStore extends Space.ui.Store

  Dependencies:
    cases: 'Cases'
    actions: 'Actions'

  setInitialState: ->

    limit = 5

    {
      case: null
      cases: @cases.find currentStatus: { $lte: limit }
    }

  configure: ->

    @listenTo(
      @actions.setCurrentCase, @_setCurrentCase
    )

  _setCurrentCase: (caseId) ->
    @setState 'case', @cases.findOne caseId

When I log @getState 'case' in the _setCurrentCase function, I get the whole (why?) object from setInitialState, with the correct case document on the case property.

class App.CasesShowController

  Dependencies:
    actions: 'Actions'
    tracker: 'Tracker'
    router: 'Router'

  onDependenciesReady: ->

    self = this

    @router.route 'cases.show',
      path: 'show/:_id'

      waitOn: ->
        singleSubs.subscribe 'case', @params._id

      onBeforeAction: ->
        caseId = @params._id

        self.tracker.nonreactive -> self._setCurrentCase caseId

  _setCurrentCase: (caseId) ->
    @actions.setCurrentCase caseId

This seems to work, when I log the caseId, I get the right _id.

class App.CasesShowMediator extends Space.ui.Mediator

  @Template: 'CasesShow'

  Dependencies:
    store: 'CasesStore'

  templateHelpers: ->

    state: => {
      case: @store.getState().case
    }

This is strange. When I go into the templateHelpers function and log @store.getState().case, I get null, which is the initial value. But in the store's _setCurrentCase function, it logged the state object with the correct case (although I would have expected only the case).

As I already said, the code worked on another branch, with an older version of space:ui, two days ago. I think getState and setState do weird stuff. Or did I miss some changes? Or is it because of a wrong order (I don't think that's really possible)?

Thank you :)

-- Additional question: Are states reactive?

backward compatibility/ final api

Hey there :)
I just updated space-ui to find out there are a lot of new things
I like the new way of handling events and the new Space.ui.Application - things are much cleaner, nice!

However, the new version breaks backward compatibility. It is not documented and there is no guide on how to migrate from older versions. I'm wondering when there'll be a stable api, so that such radical api changes won't happen anymore (in the major version)?

As you might have guessed I have some questions ;)

  • Events and helpers are not defined in the mediator anymore, right? It took me some time migrating to this concept and there are cases where I use data from the store in my helpers. How could this work? Going back to regular helpers and events to seems like adding another layer, which I'd like to prevent. Maybe we could keep helpers and events in the mediator. Thoughts?
  • I still have all my mediators and controllers on an App namespace. This seems not supported by the new Space.ui.Application, unless I map all controllers and collections manually or override the run method.

I'd love to know what you think before trying to move to the newest version of space-ui, as it seems to be quite some work /: You seem to be experimenting with new ideas to find out what's the best way to do things, and I like that. But I'm using space-ui in production and it's really hard to get up to date.

Thanks :)

Question

Hi,

Can it be complimented with famous-views ?

Thanks, Pavel

Error on startup: Cannot read property 'constructor' of undefined

I'm refactoring an existing app to use space-ui.

This error happens on client startup. My browser console points to line 56 of space:messaging/source/controller.coffee:

  @_isEvent: (message) ->
    message.__super__.constructor is Space.messaging.Event

I've been investigating for a long time without any clue 😔

Here is the refactored app:
https://bitbucket.org/npvn/meteor-url-shortener/commits/branch/space-ui

Any help is greatly appreciated!

Improve APIs and debugging when working in Javascript

A lot of the APIs in space where inspired by the possibilities of Coffeescript. In some parts, it became quite ugly to write the same functionality in Javascript. To get more people on board it is definitely important that writing Space applications in Javascript should be equally awesome 😉

Here are some key areas where improvements are needed:

Extending classes

In Coffeescript we have class Test extends Other which gives us good debugging in browser consoles. The space framework provies Space.Object.extend which also gives a lot of power to Javascript, but unfortunately creates a lot of anonymous _Class, because it is based on the coffeescript inheritance.
To solve this problem, an advanced API is necessary that is able to create named classes and assign them to namespaces etc. (in work)

Static methods (meta-programming)

One of the nicest parts of Coffeescript is the static meta-programming and the Space framework is heavily based on this sugar. However, it is not as nice in Javascript and sometimes leads to quite bloated code that could be much simpler. (in work)

Stores are not initialized on the app start

I use space:ui 3.4.4.

The store singletons are lazily initialized when another component depend on it.
However a component can emit an action without depending on the store. I think the action emitter shouldn't need to know what stores listen for the action.
So the store can miss the action when it wasn't initialized.

I've fixed this by adding the following code parts to my Space.Application subclass:

MyApp.Application = (function() {
  extend(Application, Space.Application);

  function Application () {
    this._stores = [];
    Application.__super__.constructor.apply(this, arguments);
  }

  _.extend(Application.prototype, {

    configure: function () {
      this.configureStores();
    },

    configureStores: function () {
      this.mapStore('MyStore', MyStoreConstructor);
    },

    mapStore: function (name, store) {
      this.injector.map(name).toSingleton(store);
      this._stores.push(name);
    },

    initializeStores: function () {
      var injector = this.injector;
      this._stores.forEach(function (storeName) {
        injector.get(storeName);
      });
    },

    run: function () {
      this.initializeStores();
    }

  });

  return Application;
})();

Tutorial

Do you plan to release a tutorial? A video tutorial or talk at a Meteor devshop would be great. I think it's hard to get into this concept if you haven't used it before.

Also, I'm building quite a complex app at the moment and thinking about giving it a better structure.
Do you think you can build any kind of app with this concept? When I think about simple examples, where would I put

  • allow/ deny rules,
  • collection helpers
  • hooks or
  • schemas?

What about my current iron controllers? Does this concept influence my rendered functions (which are more than 100 lines in some cases) or my events which often are more than 100 lines of code as well for validation, error messaging, notifications and collection the information to save?

Thanks :)

Reflux

Sorry for creating all the issues but I'd love to learn this as your code just looks too nice and clean :)
Have you seen Reflux? It's based on facebook's flux but gets rid of the dispatcher and seems to be easier to understand.

See

By the way: will you maintain this package or is it going to stay as-is and die slowly? Just asking because this happens to quite some packages ..

Routes only work in namespace

Hey there :)

I'm still using [email protected] or so, I hope you still remember how that version worked ;)
I want to move my app into packages as I think I will get a better structure then. I will not have my global App namespace anymore then, so before doing that, I tried to remove it.

All I did was changing this

@injector.map('PatientsNewController').toSingleton App.PatientsNewController
# to
@injector.map('PatientsNewController').toSingleton PatientsNewController

and

class App.PatientsNewController
# to
class @PatientsNewController

I don't know why, but it just stopped working. I get my "not found" page, and the url changes to undefined. Do you have an idea what might be wrong?

I can access PatientsIndexController from the console and when I log it before mapping it, I can get it there, too. Really strange :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.