I created a Ext.Mixin component and would like to call a function of it from another component. How do I have to do that? Must be very obvious, but I can't see right now.
EDIT:
Ext.define('ABC.mixin.MyMixin', {
extend: 'Ext.Mixin',
mixinConfig: {
after: {
},
before: {
initComponent: 'init'
}
},
init: function () {
let me = this;
myfunction();
},
myfunction: function () {
//do stuff
}
}
How do I call myfunction() ?
When you include a mixin to a component all of the functions the mixin provides are included to the component itself.
So when you have a reference to your created component you cann call the function on the component itself.
Ext.define('ABC.mixin.MyMixin', {
extend: 'Ext.Mixin',
myfunction: function () {
//do stuff
}
});
Ext.define('ABC.view.MyView', {
mixins: ['ABC.mixin.MyMixin'],
// ...other config stuff
});
let myView = Ext.create('ABC.view.MyView'); // concreate Object of the class ABC.view.MyView
myView.myfunction(); // we can call the function of the mixin on the Object directly.
For more information see the ExtJs documentation
The API Docs seem to provide the information you need. You just include your mixin in the component you need, like so:
Ext.define('ABC.view.MyComponent', {
mixins: ['ABC.mixin.MyMixin'],
initComponent() {
this.myfunction();
this.callParent();
}
});
And from the component's scope, call the mixin's functions you need
Related
I am trying to write a game using lance-gg library.
I tried to implement a simple aframe component, that print entity's object3D position and rotation in world space.
The problem is that I cannot access this from within the component event listener.
I have tried to search around I've found this [thread] (Aframe unregister component), so I guess the problem is the initialization order. I have tried to include a component directly from the index but it does't worked either.
// aSeparateFile.js
AFRAME.registerComponent(
'custom-component',
{
schema: {
controllerID: {
type: 'string',
default: 'none'
}
},
init: () => {
console.log('componet has been created');
console.log(this);
},
tick: () => {
console.log(this.el.object3D.rotation);
console.log(this.el.object3D.position);
}
}
);
this component was created in a separate file called aSeparateFile.js, I include this file from my AFrameRenderer extension. Like this:
import {AFRAMERenderer} from 'lance-gg';
import './aSeparateFile.js';
I would like to know the best way to register a custom component with lance-gg.
Don't use arrow functions that will bind the methods to the wrong this. Use regular functions instead:
AFRAME.registerComponent(
'custom-component',
{
schema: {
controllerID: {
type: 'string',
default: 'none'
}
},
init: function () {
console.log('componet has been created');
console.log(this);
},
tick: function () {
console.log(this.el.object3D.rotation);
console.log(this.el.object3D.position);
}
});
In my Vue App, I use a drag and drop system. (I use https://github.com/Vivify-Ideas/vue-draggable FYI).
In my data() I have to declare parameters like this:
data() {
draggable: {
dropzoneSelector: 'ul',
draggableSelector: 'li',
/* some extra parameters who are no incidence with my problem */
onDrop: function(event) {
callLayout();
}
}
}
You can see that I have a onDrop: function(event) {}. I would like to call a function I declared like that.
methods: {
callLayout : function() {
console.log('TOTO')
}
}
I tried to use this.callLayout() etc.. But still get this error:
callLayout is not a function/not defined.
Do you have an idea of what I'm doing wrong ? =(
You have to use arrow function or use bind for onDrop function. This gives an error because in onDrop function this keyword does not refers to your component.
data() {
draggable: {
dropzoneSelector: 'ul',
draggableSelector: 'li',
/* some extra parameters who are no incidence with my problem */
onDrop: (event)=> { // Chnage to arrow function
this.callLayout(); // Use this here.
}
}
}
Hi I would like to know what's the proper way to update a property on a component from the route?.
A little background on what I want to do:
I have two custom Buttons that I called CardButtons (based on material desing) next to one blank area called description, what I want is to create a hover event that triggers an ajax call to retrive detailed data from a data base and render it on the description area.
CHECK UPDATE
So far I have created a route like this:
export default Ember.Route.extend({
selectedModule: '',
model: function () {
return {
selectedModule: 'employeeModule'
};
},
actions: {
showDescription: function (params) {
this.set('model.selectedModule', params);
}
}});
My route template call my component like this:
<div class="row">
{{sis-db-description-render idTitle=model.selectedModule}}
</div>
and the component is defined like this:
export default Ember.Component.extend({
info: null,
ready: false,
didInsertElement: function () {
this.queryData();
},
queryData: function (){
/** Does an Ember.$.post request to the API with the idTitle as param**/
}
});
the first time this executes it load perfectly the detail data but when I try to refresh the data the event does not trigger a second call. I bealive it is beacause I'm not updating the model in a proper way.
Any idea on how to update the component property?
UPDATE:
Thanks to #kumkanillam I was able to find a way on my route I added the next code:
setupController: function (controller, model) {
this._super(...arguments); //if its new/index.js route file then you can use controller argument this method.
controller.set('selectedModule', 'employeeModule');
},
actions: {
showDescription: function (params) {
console.info(params);
this.controllerFor('new.index').set('selectedModule', params);
}
}
By doing so now the view updates the content every time, I still don't know if this is the correct way to do it but it works for now.
In the below code, model is not defined in route. it's defined in corresponding controller through setupController hook.
showDescription: function (params) {
this.set('model.selectedModule', params);
}
So in your case either you can define action in controller and update model.selectedModule
If you want to do it in route,
showDescription: function (params) {
let cont = this.controllerFor('route-name');
cont.set('model.selectedModule', params);
}
I'm trying to build a simple app in vue and I'm getting an error. My onScroll function behaves as expected, but my sayHello function returns an error when I click my button component
Property or method "sayHello" is not defined on the instance but
referenced during render. Make sure to declare reactive data
properties in the data option. (found in component )
Vue.component('test-item', {
template: '<div><button v-on:click="sayHello()">Hello</button></div>'
});
var app = new Vue({
el: '#app',
data: {
header: {
brightness: 100
}
},
methods: {
sayHello: function() {
console.log('Hello');
},
onScroll: function () {
this.header.brightness = (100 - this.$el.scrollTop / 8);
}
}
});
I feel like the answer is really obvious but I've tried searching and haven't come up with anything. Any help would be appreciated.
Thanks.
But for a few specific circumstances (mainly props) each component is completely isolated from each other. Separate data, variables, functions, etc. This includes their methods.
Thus, test-item has no sayHello method.
You can get rid of the warning by using .mount('#app') after the Vue instance rather than the el attribute.
Check the snippet below;
var app = new Vue({
data: {
header: {
brightness: 100
}
},
methods: {
sayHello: function() {
console.log('Hello');
},
onScroll: function () {
this.header.brightness = (100 - this.$el.scrollTop / 8);
}
}
}).mount('#app');
Please note; the following might not be necessary but did it along the way trying to solve the same issue: Laravel Elixir Vue 2 project.
I have a listener setup in my componentDidMount:
updateBasketTotal: function() {
BasketService.getBasketTotal(function(data){
this.setState({
selectedPeopleCount: data.TotalMembers
});
}.bind(this));
},
componentDidMount: function() {
this.updateBasketTotal();
this.subscribeToChannel(basketChannel,"selectAll",this.listenerSelectAll);
this.subscribeToChannel(basketChannel,"removePersonFromBasket",this.listenerRemovePersonFromBasket);
this.subscribeToChannel(basketChannel,"addPersonToBasket",this.listenerAddPersonToBasket);
this.subscribeToChannel(basketChannel,"addArrayToBasket",this.listenerAddArrayToBasket);
},
listenerAddArrayToBasket: function(data){
BasketService.addPerson(data.arrayToPush,function(){
this.updateBasketTotal();
});
},
listenerAddPersonToBasket: function(data){
BasketService.addPerson(data.personId,function(){
this.updateBasketTotal();
});
},
listenerRemovePersonFromBasket: function(data){
BasketService.removePerson(data.personId,function(){
this.updateBasketTotal();
});
},
listenerSelectAll: function(data){
BasketService.selectAll(data.selectAll, function () {
this.updateBasketTotal();
});
}
However, if I publish a message when I'm not on this page, I get an error:
this.updateBasketTotal is not a function
Can anyone please tell me how I can use this.updateBasketTotal?
I think its a problem with 'this' but not sure how to fix it. Thanks in advance
UPDATE:
Have tried adding bind() to the listener:
listenerAddPersonToBasket: function(data){
BasketService.addPerson(data.personId,function(){
this.updateBasketTotal();
}.bind());
},
But no joy, any ideas?
I assume your component is unsubscribing to those channels in componentWillUnmount to avoid resource leaks and duplicate subscriptions.
The asynchronous callbacks should call isMounted to ensure the component is still mounted before attempting anything else.
BasketService.selectAll(data.selectAll, function () {
if (this.isMounted()) {
this.updateBasketTotal();
}
}.bind(this));
I don't know if the isMounted check will solve your problem since that may also not be a function anymore. If it isn't, you might consider adding your own property to track whether the component is mounted or not and check that rather calling a function.
listenerAddArrayToBasket: function(data) {
var _this = this;
BasketService.addPerson(data.arrayToPush,function() {
_this.updateBasketTotal();
});
}
or
listenerAddArrayToBasket: function(data) {
BasketService.addPerson(data.arrayToPush,function() {
this.updateBasketTotal();
}.bind(this));
}
React does not bind context by default, you have to do it yourself. In your example this would refer to callback function, not to react object.
You can either assign react context to a variable and use it inside your callback, or bind context directly to callback.
Here is the great article explaining contexts in JavaScript
Also in ES6 it's possible to use double arrow declaration
class SomeComponent extends React.Component {
updateBasketTotal() {
....
}
lisneterAddArrayToBasket() {
BasketService.addPerson(data.arrayToPush, () => {
this.updateBasketTotal()
})
}
}
You can use babel to compile your ES6 code to old plain ES5 :)