Ampersand.js – Minimalistic Approach to not so minimalistic Problems

7fa6c608c58feec29a780ba5f7700068?s=47 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.

7fa6c608c58feec29a780ba5f7700068?s=128

Kamil Ogórek

September 11, 2014
Tweet

Transcript

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

  2. X-Team Senior Client-side Engineer

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

  4. 
 Ampersand.js

  5. 
 Ampersand.js

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

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

  8. None
  9. Overview

  10. None
  11. State ampersand-state

  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; } } } });
  13. Models ampersand-model ampersand-state ampersand-sync

  14. Collections

  15. ampersand-collection ! !

  16. ampersand-collection ampersand-state

  17. ampersand-collection ampersand-subcollection ! !

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

  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; } });
  20. ampersand-collection ampersand-subcollection ampersand-rest-collection ! !

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

  22. Views

  23. ampersand-view ! !

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

  25. var PersonRowView = AmpersandView.extend({ template: "<li><span data-hook='name'></span><span data-hook='age'></span><a data- hook='edit'>edit</a></li>",

    ! events: { "click [data-hook=edit]": "edit" }, ! bindings: { "model.name": { type: 'text', hook: 'name' }, ! "model.age": { type: 'text', hook: 'age' } }, ! edit: function () {...} });
  26. ampersand-view ampersand-collection-view !

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

  28. ampersand-view-switcher ampersand-view

  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'); } });
  30. ampersand-view ampersand-collection-view ampersand-view-switcher ampersand-form-view ! !

  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."; } ] }) ] });
  32. ampersand-view ampersand-collection-view ampersand-view-switcher ampersand-form-view ampersand-input-view ! !

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

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

  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 !

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

  37. text

  38. text class

  39. text class attribute

  40. text class attribute value

  41. text class attribute value booleanClass

  42. text class attribute value booleanClass booleanAttribute

  43. text class attribute value booleanClass booleanAttribute toggle

  44. text class attribute value booleanClass booleanAttribute toggle switch

  45. text class attribute value booleanClass booleanAttribute toggle switch innerHTML

  46. Router

  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) {...} });
  48. Mixins ampersand-class-extend

  49. ampersand-collection-rest-mixin

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

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

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

  53. Ampersand CLI

  54. Starting a new app

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

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

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

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

    Generating models from JSON Generating forms from models Configuring the generated code
  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' }
  60. Philosophy

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

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

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

  64. Everything is separate commonjs module

  65. Everything is hosted on npm

  66. Everything should be fully tested

  67. Everything has separate git repo

  68. None
  69. Everything has separate git repo separate issues

  70. Everything has separate git repo separate issues separate life

  71. Everything do one thing and do it well

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

  73. None
  74. Summary

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

  76. Thank You @kamilogorek