As I’m still in the very beginning of Ember learning curve, I wonder what is the best and correct way to implement the following functionality.
- I have to display a shop working hours like in the attached screenshot.
- as you can see some days have their hours entered, some do not. I have to display all the 7 week days, no matter if the hours were entered or not, - set the state of the day as Closed and disable its corresponding hours fields in this case.
- how to save the entered hours:
- by every modified/created day ? (by adding
focus-out
to every opens/closes hours fields, for ex.?) - all the days via the Save button
- saving all the days, no matter if they have hours entered (anyway, every shop will have 7 days with one or another state, - closed, open, divided (i.e. with a break) ?
- how can all the hours values be caught if they don’t have IDs in case of new records ?
- by every modified/created day ? (by adding
Here is how I defined a template:
# templates/working-hours.hbs
...
<form {{action "saveHours" on="submit"}}>
{{#each weekdays as |weekday|}}
{{weekday-row weekday=weekday modelDays=model}}
{{/each}}
<div class="float-right">
<button type="submit" class="btn btn-success">{{t 'buttons.save'}}</button>
</div>
</form>
...
Here is the component passed in to the above for
loop:
#templates/components/weekday-row.hbs
<div class="form-group row">
<label for="state" class="col-sm-2 col-form-label">{{dayRow.name}}</label>
<div class="col-sm-2">
<select class="form-control" onchange={{action "selectState" value="target.value"}}>
{{#each states as |state|}}
<option value={{state.id}} selected={{eq state.id dayRow.state}}>{{state.name}}</option>
{{/each}}
</select>
</div>
<div class="col-sm-2">
{{input type="time"
class="form-control"
min="06:00"
max="22:00"
disabled=isClosed
pattern="[0-9]{2}:[0-9]{2}"
focus-out="alertMessage"
value=dayRow.opens
}}
</div>
<label for="closes" class="col-form-label">{{t 'working.hours.labels.to'}}</label>
<div class="col-sm-2">
{{input type="time"
class="form-control"
min="06:00"
max="22:00"
disabled=isClosed
pattern="[0-9]{2}:[0-9]{2}"
focus-out="alertMessage"
value=dayRow.closes
}}
</div>
</div>
{{#if isDivided}}
<div class="form-group row">
<div class="col-sm-2 offset-sm-2">{{t 'working.hours.labels.and'}}</div>
<div class="col-sm-2">
{{input type="time"
class="form-control"
min="06:00"
max="22:00"
disabled=isClosed
pattern="[0-9]{2}:[0-9]{2}"
value=dayRow.opens
}}
</div>
<label for="closes"class="col-form-label">{{t 'working.hours.labels.to'}}</label>
<div class="col-sm-2">
{{input type="time"
class="form-control"
min="06:00"
max="22:00"
disabled=isClosed
pattern="[0-9]{2}:[0-9]{2}"
value=dayRow.closes
}}
</div>
</div>
{{/if}}
And finally, the component itself:
# components/weekday-row.js
import Component from '@ember/component';
import { inject as service } from '@ember/service';
import { computed } from '@ember/object';
import EmberObject from '@ember/object';
export default Component.extend({
constants: service(),
weekday: null,
state: null,
modelDays: [],
weekdays: [],
states: [],
tagName: '',
dayRow: null,
init() {
this._super(...arguments);
this.states = this.get('constants.states');
this.dayRow = this.buildDayRow();
},
buildDayRow() {
let dayRow = EmberObject.create({ name: this.get('weekday.name')});
let foundDay = this.get('modelDays').findBy('day', this.get('weekday.day'));
if (typeof foundDay != 'undefined') {
dayRow.set('state', foundDay.get('state'));
dayRow.set('opens', foundDay.get('opens'));
dayRow.set('closes', foundDay.get('closes'));
} else {
let closedState = this.get('states')[1];
dayRow.set('state', closedState.id);
}
return dayRow;
},
isClosed: computed('dayRow.state', function() {
return this.get('dayRow').get('state') === 'closed';
}),
isDivided: computed('dayRow.state', function() {
return this.get('dayRow').get('state') === 'divided';
}),
actions: {
selectState(state) {
this.get('dayRow').set('state', state);
this.get('dayRow').set('opens', null);
this.get('dayRow').set('closes', null);
},
alertMessage(value) {
console.log('focus off for: ' + value);
}
}
});
The route handler:
# routes/working-hours.js
import Route from '@ember/routing/route';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
import { inject as service } from '@ember/service';
export default Route.extend(AuthenticatedRouteMixin, {
currentShop: service(),
constants: service(),
setupController(controller, model) {
this._super(controller, model);
this.controller.set('weekdays', this.get('constants.days'));
},
model() {
return this.store.query('working-hour', { shop_id: this.get('currentShop.shop').get('id')});
},
...
Just in case here is how weekdays
are defined in constants.js
service:
# services/constants.js
import Service from '@ember/service';
import { inject as service } from '@ember/service';
export default Service.extend({
i18n: service('i18n'),
init() {
this._super(...arguments);
this.set('states',
[
{id: 'opened', name: this.get('i18n').t('states.open')},
{id: 'closed', name: this.get('i18n').t('states.closed')},
{id: 'divided', name: this.get('i18n').t('states.divided')}
]
);
this.set('days',
[
{day: 'monday', name: this.get('i18n').t('weekdays.monday')},
{day: 'tuesday', name: this.get('i18n').t('weekdays.tuesday')},
{day: 'wednesday', name: this.get('i18n').t('weekdays.wednesday')},
{day: 'thursday', name: this.get('i18n').t('weekdays.thursday')},
{day: 'friday', name: this.get('i18n').t('weekdays.friday')},
{day: 'saturday', name: this.get('i18n').t('weekdays.saturday')},
{day: 'sunday', name: this.get('i18n').t('weekdays.sunday')}
]
);
}
});
Thank you!!