Odoo Override Javascript Class Method - javascript

First off, my apologies - I'm a complete novice when it comes to javascript so this is a bit above my head. I'm also fairly new to Odoo and have mostly stuck with python and XML customization thus far.
I'm trying to override a javascript method within a class to replace it completely with my own version. From the Odoo documentation (https://www.odoo.com/documentation/14.0/reference/javascript_reference.html#patching-an-existing-class) this should be a simple matter of using the .include() method to patch the original class with my new method. But when I do this I get an error Error while loading mymodule.CustomControlPanelModelExtension: TypeError: ControlPanelModelExtension.include is not a function
The original Odoo code that I'm trying to override:
odoo.define("web/static/src/js/control_panel/control_panel_model_extension.js", function (require) {
"use strict";
// a bunch of code here ...
class ControlPanelModelExtension extends ActionModel.Extension {
// more code here ...
// this is the method I'm trying to override
_getAutoCompletionFilterDomain(filter, filterQueryElements) {
// original method body here
}
// more code
}
// more code
});
Below is what I came up with based on the documentation but this gives me the error Error while loading mymodule.CustomControlPanelModelExtension: TypeError: ControlPanelModelExtension.include is not a function (this error is reported in browser dev tools console).
odoo.define('mymodule.CustomControlPanelModelExtension', function(require) {
"use strict";
var ControlPanelModelExtension = require('web/static/src/js/control_panel/control_panel_model_extension.js');
ControlPanelModelExtension.include({
// override _getAutoCompletionFilterDomain
_getAutoCompletionFilterDomain: function(filter, filterQueryElements) {
// my custom implementation here
},
});
});
Any ideas what I'm doing wrong here? I've tried various other things with extends and such but I don't think I want to extend - that won't replace the function in existing instances.

The problem here is that the include function is available only for the classes that inherit from OdooClass and in this case the class you are trying to inherit is a native JavaScript class.
Then, to add a property or method to a class, the prototype property of the object class must be modified.
odoo.define('mymodule.CustomControlPanelModelExtension', function(require) {
"use strict";
const ControlPanelModelExtension = require('web/static/src/js/control_panel/control_panel_model_extension.js');
function _getAutoCompletionFilterDomain(filter, filterQueryElements) {
// your custom implementation here
}
ControlPanelModelExtension.prototype._getAutoCompletionFilterDomain = _getAutoCompletionFilterDomain;
return ControlPanelModelExtension;
});

Related

ReferenceError: [...] is not defined

I am trying to use a JS function which is in an another JS file and I have this error :
ReferenceError: Lanceur is not defined
Lanceur is my object which is defined in my second file.
I have a constructor :
public class Lanceur {
constructor(angleAiguille) {
this.angleAiguille = angleAiguille;
} // And functions .....
I have this line in my first file : lanceur = new Lanceur(0);
And I call my files in a HTML files with <script src="js/canvas.js" type="text/javascript"></script>, for example.
You need to create the class before you can create an instance of it. You also don't need the keyword public as browsers don't support it currently (Unless you're compiling this through Babel or something similar, but that wasn't obvious from your post).
In your first file include the code that makes up the class, I've added a method as an example.
class Lanceur {
constructor(angleAiguille) {
this.angleAiguille = angleAiguille;
}
someMethod() {
console.log('Firing')
}
}
You can then create an instance of it like so in your second file and call its methods.
const instance = new Lanceur;
// Calling a method...
instance.someMethod();
You can learn more about JavaScript class constructors here.

Accessing prototype function from another Javascript file keeps returning 'undefined'

I've dug into this for a couple of hours, looking at Javascript prototype accessing another prototype function, Accessing a Javascript prototype function, Trigger one prototype function from another (including itself), Cannot call prototype method from another function and around 3-4 other similar questions, and thought "ok, that doesn't seem so bad" and went to implement a solution (or three) to my particular problem. Or so I had thought!
I have a JS file (compiled from Typescript) that contains an AppComponent class and several methods with it (shortened version focused on my specific trouble follows):
AppComponent = (function () {
function AppComponent() {
var _this = this;
this.gridNo = '1';
//... and so on...
}
AppComponent.prototype.MenuSelect = function (link) {
this.tabCount = 0;
this.tables = [];
utils_1.Logging(' MenuSelect: ' + JSON.stringify(link));
var grids = link.grids;
this.ws.emit('C:GDRDN', { ds: grids });
// build up some HTML to make a table of data and return it to
// the caller
return "grid stuff!";
};
.
.
.
}
The above is loaded up into Angular 2/Node (written by another co-worker) and works just fine in the context it was written: ie it displays tables of data ('grids') when called from other components written by that co-worker in TypeScript.
But when I am generating a menu and try to access the MenuSelect prototype directly from another, 'normal', JS file like so...
function createWHeelNavigation() {
basic.navigateFunction = function () {
var grids_selected = [ 4, 11 ];
var appcomp = new AppComponent();
output = appcomp.MenuSelect(grids_selected);
// minified.js function to add children content to a DOM element
$("grid_container").add(output);
}
// other navigation menu functions...
}
createWHeelNavigation();
...I continue to get "Uncaught ReferenceError: AppComponent is not defined" when I click on that particular 'basic' menu item, even though according to what I've read in SO and elsewhere that creating a 'new' instance of the object is the way to access its prototype methods.
So before I pull my hair out and go back to rocking in the corner of my office, whispering "mommy...", I thought I would pass this around to you fine people to see where I am going wrong. I have a niggling suspicion I should be using 'this' somewhere, but my eyes are crossing, and wish to be pointed in the right direction. Thanks for your time!
I continue to get "Uncaught ReferenceError: AppComponent is not defined" w
A common JavaScript ordering issue. Make sure you are loading your js / ts in the right order.
More
Please use modules if possible. https://basarat.gitbooks.io/typescript/content/docs/tips/outFile.html

typescript definition constructor or function?

I am trying to create a typescript definition file for an existing javaScript library, but keep getting run time errors.
The library contains the following code:
/**
* Pdok namespace, will hold Api namespace
* #namespace
*/
Pdok = {};
Pdok.Api = function(config) {
/* implementation details are here... */
}
The javascript example code that was supplied works and contains the following line:
var api = new Pdok.Api(config);
I created a typescript definition file, and am able to compile without any problems. The definition looks like:
declare namespace Pdok
{
interface configOptions {
/* .. details .. */
}
class Api {
constructor(config: configOptions);
}
}
At run time, i get the following error:
Uncaught TypeError: Pdok.Api is not a constructor
What should be in my .d.ts-file to get this working?
Based on this answer https://stackoverflow.com/a/15008808/4516689 it could be that the source isn't loaded correctly.
Set a debugger; directive before your code and check to what the variable Pdok.Api is set to.
debugger;
var api = new Pdok.Api(config);
or use this
alert(Pdok.Api);
var api = new Pdok.Api(config);
it should return "function (config) { ..."

registerClass not working in javascript

I am trying to extend a class using registerClass.
derived.registerClass("derived",base);
but when i try to access the function defined in the base class using a derived object it throws the following error : 'Object doesn't support property or function FunctionName'.
When i try debugging using visual studio debugger (by placing the breakpoint on the function call and looking the current values of the object), the function is visible.
The code for base class looks something like following:
Type.registerNamespace("MyProject");
base.jam = function(refObj,primaryStringField,nestedType){
....
}
base.jam.prototype = {
testfunc: function() {
...
}
}
base.jam.registerClass("base.jam");
And the code for derived class is
Type.registerNamespace("base.pages.item");
..
base.pages.item.behavior = function() {
...
...
testFunc(); // <- this function is visible while debugging (as explained above), but throws an error while ruunning
}
base.pages.item.behavior.registerClass("base.pages.item.behavior",base.jam)

Using Meteor and javascript in an object oriented style

Please bear with me as I'm new to JS and am having trouble implementing some things with Meteor. I implemented a class in JavaScript using
function Class() {
this.property = 0
this.method = function () {
return "method called"
}
}
I made a new Meteor Collection bu using new Meteor.collection and successfully retrieved the data on the client and can display Class.property in the html template. However, I am unable to access Class.method and was wondering if there's any way to make this happen and if using Meteor.methods to define functions that take the Class instance as input is the best way to go.
For anyone still looking at this, the reason the code doesn't work is because mongodb stores documents as bson. bson, just like json, does not support functions (http://bsonspec.org) so when the above class is saved by meteor into mongo, the method is not saved as part of the document.
There is no easy elegant solution I'm aware of. I have the same issue. In order to utilise the class method you would need to instantiate the class each time you needed it, which you could implement as part of a database model.
This is not really an answer but in meteor's package manager you can add libraries like backbone.js which gives you models, collection and views and a nice router which I find very handy when making meteor apps. Backbone works well with jQuery.
My other suggestion is using a library like Mootools which unlike jQuery doesn't try to change the way you write javascript but enhancing the experience of making object oriented javascript. (see: jqueryvsmootools). With mootools you can can make a class the following way...
var MyClass = new Class({
'Implements': [Options],
//default options
'options': {
'foo': null
},
'initialize': function(options) {
this.foo = options.foo;
},
'bar' : function() {
return this.foo;
}
});
var blub = new MyClass({'foo': 'Hello World'});
blub.bar(); // "Hello World"
I was looking to do the same thing.
I found a function called "transform" that is called when getting something from a meteor collection. You can use it to add a function to a meteor object just as you require.
Here is an example of adding an "endDate" function and "remaining" functions to a meteor object
Products = new Meteor.Collection("Products", {
transform: function (doc) {
doc.endDate = function () {
// SugarJS gives us minutesAfter() which gives us a nice syntax for
// creating new Date objects
// http://sugarjs.com/api/Number/unitAfter
return ((25).minutesAfter(this.startDate));
};
doc.remaining = function () {
return this.endDate().getTime() - Date.now();
};
return doc;
}
});
Read more here:
http://www.okgrow.com/posts/2014/05/19/meteor-transform/
This approach worked beautifully for me:
http://www.okgrow.com/posts/2014/05/19/meteor-transform/
I don't know anything about Meteor, but I see a problem with your code. You're missing a semi-colon after:
this.property = 0
Without that semi-colon, the javascript interpreter will not execute the this.method assignment.

Categories