6

We start with a new application, using Ember 3.8 and bootstrap/SASS. There seem to be two add-ins available which support bootstrap within Ember, ember-boostrap and ember-cli-bootrap-sassy.

While the former implements ember components for most of the bootstrap features and also "replaces" the original bootstrap.js by it's own implementation, with the latter, it seems I can still use all the original components and js implementations.

From first glace, I would be much more comfortable with ember-cli-bootrap-sassy, since I could still use all bootstrap examples from the web, and having a "customized" version of bootstrap.js also seem somewhat counter-intuitive to me. Also, what about all the bootstrap features ember-bootstrap does not implement, but I still require? It seems like I might be ending with an appliation which would use ember-bootstrap, but additionally uses all sorts of "workarounds" for things not implemented.

Since I don't have much experience in this field, I would be glad for some recommendations and insights from experts.

Urs Meili
  • 618
  • 7
  • 19

2 Answers2

10

So first of all a disclaimer: as the author of ember-bootstrap, I am certainly a bit biased here! ;)

But I think I have strong arguments in favor of ember-bootstrap, otherwise I wouldn't have invested that ton of work. So the main one is that it follows the programming model of Ember, while using bootstrap.js directly doesn't and would often feel awkward in an Ember app:

  • You use components to render things, which in turn render the trivial markup that Bootstrap expects, rather than spreading Bootstrap flavored static markup all over the app
  • Components in ember-bootstrap strictly follow the so called "Data down Actions up" (DDAU) programming model in Ember
  • that means through declaratively assigning properties which create data bindings, the state of your app "flows" through your UI, so the rendered DOM is a direct function of your state. This is the "Data down" part, which is different than having to imperatively "call" things to achieve the same effect (like $('#myModal').modal('show'))
  • When the user interacts with your UI, actions are called, which are handled somewhere up the component tree (e.g. in a controller). These transform your state, which is used to update the UI again (unidirectional data flow)

If that sound too abstract, take this simple example of a modal component. In ember-bootstrap you would do something like this:

{{#bs-modal-simple
  open=this.showConfirmation
  title="Please confirm"
  onSubmit=(action "submit")
  onHidden=(action "close")
}}
  Some {{dynamic}} content.
{{/bs-modal-simple}}
  • The necessary Bootstrap markup is rendered automatically. You just use the component and interact with its public API (properties and actions)
  • Displaying the modal would happen by setting your showConfirmation state to true (or even having that computed automatically with a computed property). In bootstrap.js you would somehow have to imperatively call $('#myModal').modal('show')
  • the assigned actions are automatically called on your parent (component or controller) when the user initiated events happen. With bootstrap.js you would have to attach event listeners first in your JavaScript (and later remove them!): $('#myModal').on('hidden.bs.modal', function (e) { // do something }).
  • This also requires manual book keeping, while components have their life cycle hooks, so you can just dispose them at any time (like having them in an {{#if ...}} block or changing routes).

These are the main points from my point of view, but there are even a few more:

  • ember-bootstrap plays nicely with Ember's testing layer. With bootstrap.js you will at some point run into issues, for example the code uses setTimeout() calls for handling of transitions, which Ember's testing helpers don't know of, and so don't wait for. But often you have to rely in tests that your app is in a "settled state". ember-bootstrap instead integrates into Ember's so called Run Loop, so things like await click('#show-modal-button') just work (i.e. the modal will be fully visible when the Promise resolves).
  • bootstrap.js needs jQuery, while ember-bootstrap does not.

And to add one more thing: all of the above applies to Bootstrap components that need JavaScript. For just static components like badges you can just write the appropriate Bootstrap flavored markup. In fact ember-bootstrap intentionally does not provide components for these trivial Bootstrap components to not add any useless overhead.

Simon Ihmig
  • 593
  • 6
  • 6
  • I have two main concerns regarding this approach: - what if a new bootstrap version comes out? it seems to me that, since you replace bootstrap.js, I cannot use the new version reliably, unless your library is also updated. – Urs Meili Mar 06 '19 at 07:38
  • - there are lots of bootstrap examples out in the internet. Usually I can just copy-paste them to my source code, perhaps change some details, and they will run. Using your library, this is no longer the case. Instead I have to try to find out how to "translate" the example into components of your library. I guess this can be very frustrating if you're not a bootstrap expert and/or don't know the inner plumbings of your library by heart. – Urs Meili Mar 06 '19 at 07:39
  • Also, is there any real advantage of not depending on jQuery? – Urs Meili Mar 06 '19 at 07:39
  • Yes, if a new Bootstrap version comes out, _and_ that ships with updates to its JS (often it may be just CSS/Sass, which then "just works"), an update of Ember-bootstrap would be required. – Simon Ihmig Mar 07 '19 at 11:23
  • But it is developed in the open, so if nobody does it first, you are free to contribute! ;) In fact I don't believe this will be more work than rolling out your own custom integration code (see next comment). – Simon Ihmig Mar 07 '19 at 11:31
  • Second, I don't believe copy pasting examples from classic server-rendered frontend code will work for many cases in a Single Page App, where the programming model (DDAU) is just very different, see my original answer above for details. FWIW, other SPA framework integrations do exactly the same, by replacing bootstrap.js with their own framework-native code, e.g. react-bootstrap or BootstrapVue! – Simon Ihmig Mar 07 '19 at 11:32
  • Re: not using jQuery, it is very helpful when you target mobile users, as JS size is quite expensive performance-wise and dropping jQuery will save you ~30K. See my [Ember RFC to make it optional](https://github.com/emberjs/rfcs/blob/master/text/0294-optional-jquery.md) for more details! – Simon Ihmig Mar 07 '19 at 11:35
  • At least in the past migrating an existing application from Bootstrap 3 to Bootstrap 4 was even easier for me cause it has used Ember Bootstrap a lot. As mentioned in the answer Ember Bootstrap abstracts away a lot of the complex Bootstrap markup. Not mentioned in the answer: it support Bootstrap 3 and 4 at the same time. Migrating that parts was nothing more than changing a configuration option. – jelhan Mar 08 '19 at 00:16
  • This really is a comment that spans beyond ember and applies just as well to react/vue as well. Frontend frameworks _by definition_ abstract away the DOM. In fact, React-Bootstrap even provides _grid specific_ components like `row` and `col` – Donald Wasserman Mar 08 '19 at 10:53
2

To clarify one point of Simon's, is Ember Bootstrap doesn't actually use any of the underlying bootstrap.js javascript to work, so you get to lose that dependency. And since bootstrap (at least of 4.0) requires jQuery, you're tied to both.

With Ember-Bootstrap requires 0 extra jquery to work (and works on my jQuery free app).

  • Indeed. And as I have commented [here](https://stackoverflow.com/questions/54990087/using-bootstrap-with-ember-3-8/55002203?noredirect=1#comment96836315_55002203), that's what other framework integrations libraries do as well: drop bootstrap.js, roll out their own framework-optimized custom code, without using jQuery. – Simon Ihmig Mar 07 '19 at 11:39