6214

EmberJS 2.7 - how to bind attribute 'disabled' for a button

This official guide describes how you can bind a boolean property to disabled attribute of a HTML element. Yet it talks about a controller.

I have a button, that when clicked transitions the route (sorry it has to be a button and cannot be a link-to):

/templates/trails.hbs

<button type="button" class="btn btn-primary" disabled={{isEditing}} onclick={{route-action 'addNew'}}>Add New</button>

(route-action is a helper that allows me to use closure actions in routes)

/routes/trails.js

import Ember from 'ember'; export default Ember.Route.extend({ actions: { addNew() { this.transitionTo('trails.new'); } } });

So, after the button is clicked, the route is changed to 'trails.new'

/routes/trails/new.js

import Ember from 'ember'; export default Ember.Route.extend({ isEditing: true, });

This property appears to be ignored and is not bound as I had expected it would be. I also tried adding a controller:

/controllers/trails/new.js

import Ember from 'ember'; export default Ember.Controller.extend({ isEditing: true, });

So how does the official guide suggest something that seems to not work? What piece of ember magic am I missing here?

Answer1:

Your template is templates/trails.hbs but you set isEditing in a subroute controller controllers/trails/new.js

You need to have controllers/trails.js and deinfe isEditing in it.

So in routes/trails.js implement this :

actions: { willTransition: function(transition) { if(transtions.targetName === 'trails.new'){ this.controller.set('isEditing', true); } else{ this.controller.set('isEditing', false); } } }

Answer2:

After some digging around I discovered that what I was trying to do is not the right way to go about this at all. I would have to add a controller/trails.js and put the property 'isEditing' in that.

So I refactored this into a component: add-new-button. This is a far more 'ember' way.

First, I need an initializer (thanks to this question):

app/initializers/router.js

export function initialize(application) { application.inject('route', 'router', 'router:main'); application.inject('component', 'router', 'router:main'); } export default { name: 'router', initialize };

(this injects the router into the component, so I can watch it for changes and also 'grab' the currentRoute)

My code refactored into the component:

app/components/add-new-button.js

import Ember from 'ember'; export default Ember.Component.extend({ isEditing: function() { let currentRoute = this.get('router.currentRouteName'); return ~currentRoute.indexOf('new'); }.property('router.currentRouteName') });

templates/components/add-new-button.hbs

<button type="button" class="btn btn-primary" disabled={{isEditing}} onclick={{route-action 'addNew'}}>Add New</button>

templates/trails.hbs

{{add-new-button}}

The beauty of this is now I can use this button on my other top level templates to trigger route changes to the new route for each resource (and disable the button on arrival at the new route).

<strong>NOTE</strong>

return ~currentRoute.indexOf('new');

is doing a substring check on the route, if it finds 'new' returns true, otherwise returns false. See this.

In ES6 it can be replaced with (so I have!):

return currentRoute.includes('new);

Recommend

  • Duplicate records in Subform to New record
  • How can I add one row to a DataGridView?
  • startActivityForResult in onCreate getting skipped
  • How to add or plus times to NOW()
  • Ember data JSONAPI complex attribute data
  • Redux state is updated but mapStateToProps not being called
  • Vuejs lazy loading routes in webpack template
  • \"Failed to mount component” error on Laravel 5.3.10 + Vue.js 2.0.1
  • how to set values when Select2 is ready?
  • EmberJS - Manually bind controller to view
  • How to programatically add component via controller action in ember 2.x
  • chrome extension inject javascript at top of head before any other js
  • HTML select, correct option selected in DOM, but wrong item shown in firefox
  • In an Ember view, what's the best way to run code after the rerendering of an internal child vi
  • Ember.js Acceptance Testing not waiting for asynchronous data operations
  • why route of backbone needs the default route
  • Manage different base layouts in Angular2
  • Use query params of parent route to refresh the model in subroute
  • Deploying pre-encrypted configuration files to a production environment
  • Instanciate service on startup in Angular2
  • get passwords from chrome
  • React Router and Arbitrary Query Params: Page Refreshes Unintentionally on Load?
  • PWA with multiple pages
  • ASPNetCore MVC Routing Let Server Handle Specific Route
  • Laravel 4 routing not working due to .htaccess file?
  • Iron Router: How do I send data to the layout?
  • Can I have a variable number of URI parameters or key-value pairs in Laravel 4?
  • Why HTML5 Canvas with a larger size stretch a drawn line?
  • Spray.io: When (not) to use non-blocking route handling?
  • Modifying destination and filename of gulp-svg-sprite
  • GridView Sorting works once only
  • Angular 2 constructor injection vs direct access
  • Java static initializers and reflection
  • Android Google Maps API OnLocationChanged only called once
  • Busy indicator not showing up in wpf window [duplicate]
  • costura.fody for a dll that references another dll
  • Observable and ngFor in Angular 2
  • How to Embed XSL into XML
  • UserPrincipal.Current returns apppool on IIS
  • Conditional In-Line CSS for IE and Others?