Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ampersand.js – Minimalistic Approach to not so minimalistic Problems

Kamil Ogórek
September 11, 2014

Ampersand.js – Minimalistic Approach to not so minimalistic Problems

Most of the client-side frameworks those days, aim to solve all developer problems at once, even when you didn’t ask them to. What if we could let developers decide which parts of the ecosystem they want to use, instead of handing them a big monolithic black-box. Those parts could be maintained, updated and delivered separately, without any interruptions to the other parts, but they’re working together like a charm at the same time.

Not to say that very few of them let you almost never leave your terminal, fully leverage NPM, CommonJS modules and your whole build process, which is essential for rapid development. Add to that a pinch of CLI generators, code reuse on a server-side, curated list of already solved problems and you’ll get Ampersand.js – non-frameworky framework for building advanced JavaScript apps, where it’s up to you how you’ll use it. Ampersand gives you lots of tools, just enough conventions, but tons of flexibility.

Kamil Ogórek

September 11, 2014
Tweet

More Decks by Kamil Ogórek

Other Decks in Programming

Transcript

  1. Ampersand.js
    Minimalistic Approach
    to not so minimalistic
    Problems
    @kamilogorek

    View Slide

  2. X-Team
    Senior Client-side
    Engineer

    View Slide

  3. X-Labs
    A fund dedicated
    to supporting open
    source communities.

    View Slide


  4. Ampersand.js

    View Slide


  5. Ampersand.js

    View Slide


  6. @henrikjoreteg @philip_roberts @lancestout @lynnandtonic
    @lukekarrys @wraithgar

    Ampersand.js

    View Slide


  7. @henrikjoreteg @philip_roberts @lancestout @lynnandtonic
    @lukekarrys @wraithgar @kamilogorek

    Ampersand.js

    View Slide

  8. View Slide

  9. Overview

    View Slide

  10. View Slide

  11. State
    ampersand-state

    View Slide

  12. var Person = AmpersandState.extend({
    props: {
    firstName: 'string',
    lastName: 'string'
    },
    session: {
    signedIn: ['boolean', true, false],
    },
    derived: {
    fullName: {
    deps: ['firstName', 'lastName'],
    fn: function () {
    return this.firstName + ' ' + this.lastName;
    }
    }
    }
    });

    View Slide

  13. Models
    ampersand-model
    ampersand-state ampersand-sync

    View Slide

  14. Collections

    View Slide

  15. ampersand-collection
    !
    !

    View Slide

  16. ampersand-collection
    ampersand-state

    View Slide

  17. ampersand-collection
    ampersand-subcollection
    !
    !

    View Slide

  18. ampersand-subcollection
    ampersand-collection
    ampersand-collection-underscore-mixin

    View Slide

  19. var WidgetCollection = require('./mycollection');
    var SubCollection = require('ampersand-subcollection');
    !
    !
    var widgets = new WidgetCollection();
    !
    widgets.fetch();
    !
    var favoriteWidgets = new SubCollection(widgets, {
    where: {
    awesome: true
    },
    comparator: function (model) {
    return model.rating;
    }
    });

    View Slide

  20. ampersand-collection
    ampersand-subcollection
    ampersand-rest-collection
    !
    !

    View Slide

  21. ampersand-rest-collection
    ampersand-collection-rest-mixin
    ampersand-collection
    ampersand-collection-underscore-mixin

    View Slide

  22. Views

    View Slide

  23. ampersand-view
    !
    !

    View Slide

  24. ampersand-view
    ampersand-collection-view
    ampersand-state
    ampersand-dom-bindings

    View Slide

  25. var PersonRowView = AmpersandView.extend({
    template: "hook='edit'>edit",
    !
    events: {
    "click [data-hook=edit]": "edit"
    },
    !
    bindings: {
    "model.name": {
    type: 'text',
    hook: 'name'
    },
    !
    "model.age": {
    type: 'text',
    hook: 'age'
    }
    },
    !
    edit: function () {...}
    });

    View Slide

  26. ampersand-view
    ampersand-collection-view
    !

    View Slide

  27. ampersand-view
    ampersand-collection-view
    ampersand-view-switcher
    !
    !

    View Slide

  28. ampersand-view-switcher
    ampersand-view

    View Slide

  29. var pageSwitcher = new ViewSwitcher(pageContainer, {
    waitForRemove: true,
    hide: function (oldView, newView, cb) {
    oldView.el.classList.add('animateOut');
    setTimeout(cb, 1000);
    },
    show: function (newView, oldView) {
    document.title = newView.pageTitle || 'app name';
    document.body.scrollTop = 0;
    !
    app.currentPage = newView;
    !
    newView.el.classList.add('animateIn');
    }
    });

    View Slide

  30. ampersand-view
    ampersand-collection-view
    ampersand-view-switcher
    ampersand-form-view
    !
    !

    View Slide

  31. var FormView = require('ampersand-form-view');
    var InputView = require('ampersand-input-view');
    !
    var AwesomeFormView = new FormView({
    submitCallback: function (obj) {
    console.log('form submitted! Your data:', obj);
    },
    validCallback: function (valid) {
    if (valid) {
    console.log('The form is valid!');
    } else {
    console.log('The form is not valid!');
    }
    },
    fields: [
    new InputView({
    name: 'client_name',
    label: 'App Name',
    placeholder: 'My Awesome App',
    value: 'hello',
    tests: [
    function (val) {
    if (val.length < 5) return "Must be 5+ characters.";
    }
    ]
    })
    ]
    });

    View Slide

  32. ampersand-view
    ampersand-collection-view
    ampersand-view-switcher
    ampersand-form-view
    ampersand-input-view
    !
    !

    View Slide

  33. ampersand-view
    ampersand-collection-view
    ampersand-view-switcher
    ampersand-form-view
    ampersand-input-view
    ampersand-array-input-view
    !

    View Slide

  34. ampersand-view
    ampersand-collection-view
    ampersand-view-switcher
    ampersand-form-view
    ampersand-input-view
    ampersand-array-input-view
    ampersand-select-view

    View Slide

  35. ampersand-view
    ampersand-collection-view
    ampersand-view-switcher
    ampersand-form-view
    ampersand-input-view
    ampersand-array-input-view
    ampersand-select-view
    ampersand-checkbox-view
    !

    View Slide

  36. View Bindings
    ampersand-dom-bindings
    ampersand-dom

    View Slide

  37. text

    View Slide

  38. text
    class

    View Slide

  39. text
    class
    attribute

    View Slide

  40. text
    class
    attribute
    value

    View Slide

  41. text
    class
    attribute
    value
    booleanClass

    View Slide

  42. text
    class
    attribute
    value
    booleanClass
    booleanAttribute

    View Slide

  43. text
    class
    attribute
    value
    booleanClass
    booleanAttribute
    toggle

    View Slide

  44. text
    class
    attribute
    value
    booleanClass
    booleanAttribute
    toggle
    switch

    View Slide

  45. text
    class
    attribute
    value
    booleanClass
    booleanAttribute
    toggle
    switch
    innerHTML

    View Slide

  46. Router

    View Slide

  47. var AppRouter = AmpersandRouter.extend({
    routes: {
    "help": "help", // #help
    "search/:query":"search", // #search/kiwis
    "search/:query/p:page": "search" // #search/kiwis/p7
    },
    !
    help: function() {...},
    !
    search: function(query, page) {...}
    });

    View Slide

  48. Mixins
    ampersand-class-extend

    View Slide

  49. ampersand-collection-rest-mixin

    View Slide

  50. ampersand-collection-rest-mixin
    ampersand-collection-underscore-mixin

    View Slide

  51. ampersand-collection-rest-mixin
    ampersand-collection-underscore-mixin
    ampersand-domthing-mixin

    View Slide

  52. ampersand-collection-rest-mixin
    ampersand-collection-underscore-mixin
    ampersand-domthing-mixin
    ampersand-react-mixin

    View Slide

  53. Ampersand CLI

    View Slide

  54. Starting a new app

    View Slide

  55. Starting a new app
    Generating form, view, model or collection

    View Slide

  56. Starting a new app
    Generating form, view, model or collection
    Generating models from JSON

    View Slide

  57. Starting a new app
    Generating form, view, model or collection
    Generating models from JSON
    Generating forms from models

    View Slide

  58. Starting a new app
    Generating form, view, model or collection
    Generating models from JSON
    Generating forms from models
    Configuring the generated code

    View Slide

  59. // .ampersandrc
    !
    {
    framework: 'hapi',
    indent: 4,
    view: '',
    router: '',
    model: '',
    page: '',
    collection: '',
    clientfolder: 'client',
    viewfolder: 'views',
    pagefolder: 'pages',
    modelfolder: 'models',
    formsfolder: 'forms',
    collectionfolder: 'models',
    makecollection: true,
    approot: '',
    force: false,
    quotes: 'single'
    }

    View Slide

  60. Philosophy

    View Slide

  61. "Optimize for change,
    it's the only constant."
    @HenrikJoreteg
    10 Sep 2014

    View Slide

  62. It's not about
    solving a problem,
    it's about how you
    approach it

    View Slide

  63. It's easier to learn
    only things you need
    to know

    View Slide

  64. Everything
    is
    separate commonjs
    module

    View Slide

  65. Everything
    is
    hosted on npm

    View Slide

  66. Everything
    should be
    fully tested

    View Slide

  67. Everything
    has
    separate git repo

    View Slide

  68. View Slide

  69. Everything
    has
    separate git repo
    separate issues

    View Slide

  70. Everything
    has
    separate git repo
    separate issues
    separate life

    View Slide

  71. Everything
    do
    one thing
    and do
    it well

    View Slide

  72. Leverage existing
    solutions and don't
    reinvent the wheel

    View Slide

  73. View Slide

  74. Summary

    View Slide

  75. !
    http://ampersandjs.com/contribute
    http://issues.ampersandjs.com
    https://github.com/ampersandjs

    View Slide

  76. Thank You
    @kamilogorek

    View Slide