SetupController for Component Ember - javascript

I have a component which adds a class for an animation after 5 seconds
export default Ember.Component.extend({
tagName: 'div',
classNames: ['gears'],
isVisible: false,
_startTimer: Ember.on('didInsertElement', function () {
var _this = this;
this._visibleTimer = Ember.run.later(this, function () {
_this._visibleTimer = null;
_this.set('isVisible', true);
}, 5000);
}),
_endTimer: Ember.on('willDestroyElement', function () {
if (this._visibleTimer) {
Ember.run.cancel(this, this._visibleTimer);
}
})
});
<i class="fa fa-cog fa-fw big {{if isVisible 'fa-counter'}}"></i>
My Problem is that in a specific a Route i need to set isVisible: true
I know that in Ember we can access by the route to the controller by setUpController but what if i want to set isVisible: true for a Component?
If this is not possible , are there other ways to achieve it? Maybe inside the component itself?

This sounds like a problem that could be resolved through Ember.Service. You can go about it in a couple ways, but the more straightforward might be to inject the service into the component and bind isVisible.
Something like:
export default Ember.Service.extend({
isVisible: false
});
export default Ember.Component.extend({
visibility: Ember.inject.service(),
isVisible: Ember.computed.alias('visibility.isVisible')
});
export default Ember.Route.extend({
visibility: Ember.inject.service(),
afterModel() {
this.set('visibility.isVisible', true);
}
});

Related

Vue component using computed property of the mixin

I have a simple component that uses mixin that's shared across multiple components with similar functionality.
When I run it I seem to be getting
Property or method "activeClass" is not defined on the instance but
referenced during render.
Here's my mixin
<script>
export default {
data() {
return {
opened: false,
identity: ''
}
},
computed: {
activeClass() {
return {
active: this.opened
};
}
},
created() {
window.EventHandler.listen(this.identity + '-toggled', opened => this.opened = opened);
},
methods: {
toggle() {
window.EventHandler.fire('toggle-' + this.identity);
}
}
}
</script>
and my component
<template>
<span class="pointer" :class="activeClass" #click="toggle"><i class="fas fa-search"></i></span>
</template>
<script>
import Trigger from '../../mixins/Trigger';
export default {
data() {
return {
mixins: [Trigger],
data() {
return {
identity: 'language'
}
}
}
}
}
</script>
For some reason I cannot seem to be able to access activeClass computed property from within the component. Any idea why is this happening?
Try to move mixin to components main scope. Not in data function rerurn

Access a component and trigger click event from App.vue component

In my template I have one click event
<span v-on:click="showGalery()">
And I am using one method for it
export default {
name: 'osaka',
data: function () {
return {
galery: false,
}
},
methods: {
showGalery () {
this.galery = true
}
}
}
Is it possible to trigger this method from App.vue template where is my nav and router links is located?
I am using vue-webpack template.
I have components, router.js, App.js and main.js structure.
Remember Vue has a one way data flow, so if you want to set something on the component you can simply pass a prop and use a watcher to trigger the change:
Vue.component('gallery', {
template: `<div v-show="gallery">Gallery</div>`,
props: {
show: {
type: Boolean,
default: false
}
},
created() {
this.gallery = this.show;
},
watch: {
show(val) {
this.gallery = val;
}
},
data() {
return {
gallery: false
}
}
});
Then in the parent you would have:
new Vue({
el: '#app',
data: {
showGallery: false
}
});
And use the following markup:
<gallery :show="showGallery"></gallery>
See this JSFiddle: https://jsfiddle.net/yx1uq370/
Incidentally, if you just want to show hide the entire component, then you can just use v-show on the component itself which
Vue.component('gallery', {
template: `<div>Gallery</div>`
});
new Vue({
el: '#app',
data: {
showGallery: false
}
});
Then your markup:
<gallery v-show="showGallery"></gallery>
And here's the fiddle for that: https://jsfiddle.net/gfr9kmub/
One final thing, are you sure that you really need to trigger this from your nav? I would assume that your nav would display the views and the views themselves would take care of this type of state management. Otherwise you may want to look at vuex to handle this situation

ember js component init different function

I have a 'test-test' component which include 2 function like below:
import Ember from 'ember';
export default Ember.Component.extend({
myfunction1: Ember.on('init', function() {
alert(123);
}),
myfunction2: Ember.on('init', function() {
alert(1234);
}),
});
On the Application.hbs I call
{{#test-test}}{{/test-test}}
Of course the result will be 2 alert(123) and alert(1234).
What should I do if I want it to init only 1 function such as myfunction1 and do not init myfunction2?
I'd do it that way:
//component/test-test.js
import Ember from 'ember';
export default Ember.Component.extend({
whatToDoOnInit: null,
initFunctions: Ember.on('init', function() {
switch(this.get('whatToDoOnInit')) {
case 1:
alert('123');
break;
//...and so on
}
}),
});
and call it like that:
//template.hbs
{{#test-test whatToDoOnInit=1}}{{/test-test}}
Of course this way you could implement another logic:
export default Ember.Component.extend({
doOneThing: false,
doAnotherThing: true,
initFunctions: Ember.on('init', function() {
if(this.get('doOneThing')) {
alert('123');
}
//...
}),
});
//template.hbs
{{#test-test doOneThing=true doAnotherThing=false}}{{/test-test}}

How to toggle class in Ember

I'm trying to figure out how I can toggle a class in a component.
I have my component that has two states: active and desactive. When I want to active it, I need add the class active.
Currently I'm using jQuery addClass and removeClass.
Component.js:
SiteApp.BookingBoxComponent = Ember.Component.extend({
actions: {
open: function (element) {
this.sendAction('open', this.$());
},
close: function (element) {
this.sendAction('close', this.$());
},
}
});
Controller.js:
SiteApp.IndexController = Ember.Controller.extend({
actions: {
open: function (element) {
element.addClass('event--active');
},
close: function (element) {
element.removeClass('event--active');
},
}
});
It is working, but I have this feeling that Ember has something build in that will help with this.
Or you could do
App.AComponent = Ember.Component.extend({
isOpen: false,
actions: {
toggleOpen: function (element) {
this.toggleProperty('isOpen');
}
}
});
Hbs
<div class="{{if isOpen 'opened' 'closed'}}">
...
</div>
See Ember's documentation on Templates: Conditionals. Essentially conditionals allow you to use expressions in your templates with variables declared in components/controllers. So, instead of accessing DOM in your components/controllers (which is not the Ember-way of doing things), you can do:
App.AComponent = Ember.Component.extend({
isOpen: false,
actions: {
open: function (element) {
this.set('isOpen', true);
},
close: function (element) {
this.set('isOpen', false);
}
}
});
And in the template:
<div class="{{if isOpen "event--active"}}">
...
</div>

How do actions work in Ember Mixins?

I am trying to develop my first mixin but I'm having trouble getting the actions to play nicely.
I want my controllers to be able to toggle an editing property and to set it to false when the model is saved or rolled back. So I've written a mixin to add this capability.
in myapp/mixins/editable.js:
import Ember from "ember";
export default Ember.Mixin.create({
editing: false,
actions: {
toggleEditing: function() {
this.toggleProperty('editing');
},
cancel: function () {
console.log("editable mixin: cancel");
this.set('editing', false);
return true;
},
save: function () {
console.log("editable mixin: save");
this.set('editing', false);
return true;
}
}
});
I thought this would be great as I can have consistent edit buttons in my templates like this.
in myapp/templates/sometemplate.hbs:
{{#if editing}}
{{#if model.isDirty}}
<button class="action-icon" {{action "cancel"}}>{{fa-icon "times" title="discard changes"}}</button>
<button class="action-icon" {{action "save"}}>{{fa-icon "save" title="save changes"}}</button>
{{else}}
<button class="action-icon" {{action "toggleEditing"}}>{{fa-icon "times" title="cancel"}}</button>
{{/if}}
{{else}}
<button class="action-icon" {{action "toggleEditing"}}>{{fa-icon "pencil" title="edit"}}</button>
{{/if}}
...and I can control saving and cancelling in my route, something like this:
in myapp/route/someroute.js:
import Ember from "ember";
export default Ember.Route.extend({
model: function(params) {
return this.store.find('somemodel', params.model_id);
},
actions: {
save: function () {
console.log("route: save");
this.modelFor('somemodel').save();
},
cancel: function () {
console.log("route: cancel");
this.modelFor('somemodel').rollback();
},
}
});
However, I am now confused... what happens if the save fails? How can I plumb it together so that the editing property is set to false only when the save has successfully completed?
Is there some way to access a promise from an action on the route? Am I heading in the right direction with this?
This is possible, but there's a little bit of weirdness. Here is a JSBin demonstrating the concept. Applied to your code, you'll have to do this:
const SomeRoute = Ember.Route.extend({
actions: {
save() {
return this.modelFor('somemodel').save();
}
}
});
SomeRoute.reopen(EditableMixin);
export default SomeRoute;
Then, in your Mixin:
export default Mixin.create({
actions: {
save() {
this._super().then(() => {
this.set('editing', false);
});
}
}
});
Note that if you apply the mixin at extend time, the super chain won't be set up correctly, so you'll have to reopen the route to apply the mixin.

Categories