Javascript identifier for widget in Odoo - javascript

If you have two widget in a view. And you do something with the first widget and you want to update (call display_field) the second widget. How to have the identifier for the second widget?
For example in the extend definition of a widget:
local.FieldNewWidget = instance.web.form.AbstractField.extend({
init: function(parent, options) {
},
events: {
'click .oe_new_input_button': 'open_new_specific_form',
},
start: function() {
},
display_field: function() {
},
render_value: function() {
},
open_new_specific_form: function(event) {
var self = this;
var new_action = {
type: 'ir.actions.act_window',
name: $(event.target).data('name'),
res_model: $(event.target).data('data-model'),
res_id: $(event.target).data('res-id'),
view_mode: 'form',
view_type: 'form',
views: [[false, 'form']],
target: 'new',
context: {
},
flags: {'form': {'action_buttons': true}},
}
self.do_action(new_action, {
on_close: function() {
// I want to refresh (call display_field) the second widget here.
// What is the identifier for the second widget?
},
});
},
});

i think this will work but i don't know if it's the best solution. I think every widget knows witch view it's by using (this.view). why don't you use a special event to trigger it from one widget and listen for it in the other one.
For example Register an event listener on the widget to listen for property changing on the view:
//in first widget register the event listener:
this.view.on('property_name', this, this.your_method);
// in second widget trigger the event by setting the value
this.view.set('property_name', a_value);
i'm new to odoo javascript let me know if this works for you i think there is a better solution by using events triggering without changing properties at all.

Related

Kendo UI treelist and angular - how to determine if it's fully loaded?

In my HTML, I have:
<kendo-treelist
k-auto-bind="true"
k-data-source="dataSourceAssignment"
k-columns="Assignmentcols"
k-rebind="Assignmentcols">
</kendo-treelist>
In the JS file, I am connecting it to the data source by:
$scope.dataSourceAssignment = new kendo.data.TreeListDataSource({
transport: {
read: function (options) {
//code here
},
schema: {
model: {
id: "id",
fields: {
//fields here
},
expanded: true
}
}
});
Is there any way I could determine if the tree has fully loaded (i.e. 'no more hourglass spinning')?
I want to call a function to stop the 'loading....' UI then.
There appears to be an onDataBound event. Try adding that as an attribute of the tag.
<kendo-treelist
k-auto-bind="true"
k-data-source="dataSourceAssignment"
k-data-bound="dataBoundHandler"
k-columns="Assignmentcols"
k-rebind="Assignmentcols">
</kendo-treelist>
See: http://demos.telerik.com/kendo-ui/treelist/events

How can I make my controller call the correct view's component in extjs?

I defined a Ext.grid.Panel called JobList that has an Ext button with an itemId called myButton. JobList has a controller. In the controller I have the following code:
Ext.define('App.controller.JobList', {
extend: 'Ext.app.Controller',
refs: [
{ref: 'jobList', selector: '#jobList'},
{ref: 'myButton', selector: '#myButton'}
],
init: function(){
this.control({
'jobList': {
select: this.selectJob
}
});
},
selectJob: function(){
this.getMyButton().enable();
}
});
I then create two instances of jobList using Ext.create they have an id of jobList1 and jobList2. The problem is when I select a job in the list on jobList2 it will enable the myButton on jobList1 not jobList2. How do I correctly enable the myButton on each instance of jobList?
Try to avoid referencing by itemId, and use aliases instead:
// in App.view.JobList.js you should have
Ext.define('App.view.JobList', {
extend: 'Ext.grid.Panel',
alias: 'widget.job-list',
// ...
dockedItems: [{
xtype: 'button',
name: 'myButton',
text: 'My button',
}]
});
// and the in the App.controller.JobList.js:
// ...
'job-list': {
selectionchange: function(model, selected) {
var button = model.view.up('job-list').down('button[name=myButton]');
button.setDisabled(Ext.isEmpty(selected));
}
}
Check the example: https://fiddle.sencha.com/#fiddle/tq1
You're using global controller, so it catches events from all views that matching the query. Look at MVVM pattern in extjs5. Sencha did a great job, in MVVM each instance of view has their own instance of ViewController, so this situation will never happen. If you want to stick with MVC pattern, then you need to manually control this. Forget about refs, you can't use them if you have more than one instance of your view class. Get other components only by query from your current component. Something like:
Ext.define('App.controller.JobList', {
extend: 'Ext.app.Controller',
init: function() {
this.control({
'jobList': {
select: this.selectJob
}
});
},
selectJob: function(selectionModel){
//first of all you need to get a grid. We have only selectionModel in this event that linked somehow with our grid
var grid = selectionModel.view.ownerCt; //or if you find more ellegant way to get a grid from selectionModel, use it
var button = grid.down('#myButton');
button.enable();
}
});

Trigger function on click if View has a certain class (backbone.js)

I have a div generated by a backbone.js view. When the user clicks on this div, a class active is added to the div and the function addToSet is executed.
Problem: I want another function to be triggered when the View's div has the class active. However, my attempt shown below always cause addToSet function to run when its clicked.
Now, I remove 'click': 'addToSet' from the events function, leaving only 'click .active': 'removeFromSet'. Clicking on the div does not cause anything to happen! Is this because the event handler cannot select the div of the view itself, just the elements inside it?
Any idea how I can solve this problem? Thanks!
JS Code
SetView = Backbone.View.extend({
tagName: 'div',
className: 'modal_addit_set',
template: _.template( $('#tpl_modal_addit_set').html() ),
events: {
'click': 'addToSet',
'click .active': 'removeFromSet'
},
initialize: function(opts) {
this.post_id = opts.post_id;
},
render: function() {
$(this.el).html( this.template( this.model.toJSON() ) );
if(this.model.get('already_added'))
$(this.el).addClass('active');
return this;
},
addToSet: function() {
$.post('api/add_to_set', {
post_id: this.post_id,
set_id: this.model.get('id'),
user_id: $('#user_id').val()
});
},
removeFromSet: function() {
$.post('api/remove_from_set', {
post_id: this.post_id,
set_id: this.model.get('id')
});
}
});
Have you tried to use a :not(.active) selector for one of your event delegates? This may help differentiate between the two scenarios.
Something like this:
events: {
'click :not(.active)' : callback1
'click .active' : callback2
}
These events:
events: {
'click': 'addToSet',
'click .active': 'removeFromSet'
}
don't work and you sort of know why. From the fine manual:
Events are written in the format {"event selector": "callback"}. The callback may be either the name of a method on the view, or a direct function body. Omitting the selector causes the event to be bound to the view's root element (this.el).
So your 'click': 'addToSet' binds addToSet to a click on the view's el itself but 'click .active': 'removeFromSet' binds removeFromSet to a .active element inside the view's el.
I think the easiest solution is to have a single event:
events: {
'click': 'toggleInSet'
}
and then:
toggleInSet: function() {
if(this.$el.hasClass('active')) {
$.post('api/remove_from_set', {
post_id: this.post_id,
set_id: this.model.get('id')
});
}
else {
$.post('api/add_to_set', {
post_id: this.post_id,
set_id: this.model.get('id'),
user_id: $('#user_id').val()
});
}
}
You could use an instance variable instead of a CSS class to control the branching in toggleInSet if that makes more sense.

EXTJS, Unable to bind event handler to controller

I'm using EXTJS with Node.JS and am having difficulty with handling events in the context of the EXTJS MVC framework.
I've been able to easily register click events when defining the Event Listener in the Class Definition of the view, but can't seem to move this code into the controller.
Here's a look at my current code:
//Icon.JS (VIEW)
Ext.define('GeekFlicks.view.Icon', {
extend: 'Ext.button.Button',
alias: 'widget.icon',
height: 48,
width: 48,
text: 'icon',
draggable: true
});
//Icon.JS (CONTROLLER)
Ext.define('GeekFlicks.controller.Icon', {
extend: 'Ext.app.Controller',
models: ['Icon'],
stores: ['Icons'],
views: ['Icon'],
init: function () {
this.control({
'listener': {
click: function(c) {
alert('working');
}
}
});
},
});
Any help or explanations around how EXTJS deals with these sort of events is will be extremely helpful and much appreciated! Thanks.
Change this.control to be something like this:
'icon': {
click: function(c) {
alert('working');
}
}
You basically need to let controller know which element is going to control. I also suggest reading about using refs: [] in the controllers to easier access visual elements and views.

ExtJS and this.control query

I have an issue with the next code block:
run: function(e, row){
var me = this;
var container = Ext.getCmp('centercontainer');
try {
container.removeAll();
} catch(e) { }
// This block is called from another file, I just put it here to show you.
me.panels = [{
xtype: 'tabpanel',
id: 'containertabpanel',
items: [{
itemId: 'package',
title: me.PackageTitle
},{
itemId: 'excursion',
title: me.ExcursionTitle
}]
}];
// Reset
container.setTitle(me.EditDestinationTitle + row.data.name);
container.add(me.panels);
me.tabs = container.getComponent('containertabpanel');
// console.log(Ext.ComponentQuery.query('#containertabpanel > #package'))
me.control({
// Work with
// 'tab': {
// Doesn't work
'containertabpanel > package': {
mouseover: me.doPackage
}
})
},
Anyone knows how do I get to catch the click event of "package" item of tabpanel component?
I saw when I use just "tab" selector on this.control query, that work, but I can't get only "package" tab component.
Thank you in advance.
In your definition of your tabpanel you can specify -
listeners:{
click:{
fn: function(){
//click handling code goes here
}
}
}
If I understood correctly this is controller code and you are trying to catch an item click on the panel which is one of many in a tabpanel
What you can do is identify your panel by any property that is unique to it via the component query syntax like this: button[myprop=blah]
This syntax will match any buttons on the page with the following config:
{
xtype:'button'
myprop:'blah'
}
In your case you can try tab[itemId=package]
What you also need to be careful about is controller can listening only for events that are fired by the components. Make sure the event you are listening for is fired (check the docs). You can always fire custom events if necessary.
You need to do this
me.control({
// Work with
// 'tab': {
// Doesn't work
'containertabpanel > #package': {
mouseover: me.doPackage
}
})

Categories