How to override action_registry js in odoo [12.0] - javascript

I have the following js file that handles a widget and I would like to overwrite and add code for custom events function, but when I tried to instantiate, nothing seems to be on the object:
This a reference for the script that I want to overwrite
odoo.define('my_module.my_report', function (require) {
'use strict';
var myWidget = AbstractAction.extend(ControlPanelMixin, {
custom_events: {
},
}
core.action_registry.add('my_report', myWidget );
return myWidget
});
});
I have tried inheriting using the following:
var InheritedWidget = require('my_module.my_report);
and also:
var InheritedWidget = core.action_registry.get('my_report');
and when I tried to override, nothing seems to happen:
InheritedWidget.include({
custom_events: {
//My custom code goes here
}
})
Do you know how to override this widget or method?

You need to extend the custom_events of an existing widget.
var InheritedWidget = require('my_module.my_report');
InheritedWidget.include({
custom_events: _.extend({}, InheritedWidget.prototype.custom_events, {
//My custom code goes here
}),
});
For more details refer to the event system documentation.

Related

integration custom JS with odoo

I have a custom code with html css and Js and I want to make integration with odoo
for the first time i put the code html and css in my form view it's okay but i want to add javascript
this is the code I want to add to my module
https://codepen.io/maesi/pen/CAydp
function viewGraph(){
$('.column').css('height','0');
$('table tr').each(function(index) {
var ha = $(this).children('td').eq(1).text();
$('#col'+index).animate({height: ha}, 1500).html("<div>"+ha+"</div>");
});
}
$(document).ready(function(){
viewGraph();
});
if someone have an tuto or documentation how to be good in Js Odoo thnx to add here
Honestly, JS framework is really hard for an odoo rookie.
I search for a solution for css combine JS works too.
And finally, got some progress.
this is some trick for implement css in some condition.
<!-- add the code in your view template -->
<template id="assets_backend_weight" name="static assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<script type="text/javascript" src="/your_module/static/src/js/jsfile.js"></script>
</xpath>
</template>
odoo.define('your_module.jsfile', function (require) {"use strict";
var core = require('web.core');
var Widget = require('web.Widget');
var bgdrawer = Widget.extend({
/* <init: construct before loading DOM completely.>*/
init: function() {
var self = this;
self._super.apply(this, arguments);
//self.bgChanger();
/* this is used to register a listener on an event.
form: .on(ev, node.callback, node.context);
ev:
'resize': implement when browser resize
'DOM_updated': implement when DOM updated
...etc. */
core.bus.on('click', "div[name='in_out'] div input:checked", self.bgChanger);
core.bus.on('DOM_updated', "span[name='in_out']", self.post_bgChanger);
core.bus.on('click', "button .o_pager_next", self.post_bgChanger);
},
bgChanger: function() {
var v = $("div[name='in_out'] div input:checked").attr('data-value');
if (v =='O') { $('.o_form_sheet').css("background-color","#adff2f");}
else if(v =='I') { $('.o_form_sheet').css("background-color","#ffc0cb");}
},
post_bgChanger: function() {
if ($("span[name='in_out']")[0]){
var _str = $("span[name='in_out']")[0].innerHTML;
if (_str=="出貨") { $('.o_form_sheet').css("background-color","#adff2f");}
else if(_str=="進貨") { $('.o_form_sheet').css("background-color","#ffc0cb");}
}
},
});
var my_widget = new bgdrawer(this);
my_widget.appendTo($(".o_form_sheet"));
});
the effect like this
this took me a lot of time to achieve, so if you get work.
please vote for my answer.
In your case, I think the first step is to extend widget and define the function in it.
And construct listener to envent DOM_updated.
var your_widget = Widget.extend({
init: function() {
var self = this;
self._super.apply(this, arguments);
core.bus.on('DOM_updated', self, self.viewGraph);
},
viewGraph: function() {
// your code
},
})
and don't forget to call the widget.
var my_widget = new your_widget(this);
my_widget.appendTo($(".o_form_sheet"));

backbone js rigth initialization process

This javascript present on all site pages.
var CategoriesView = Backbone.View.extend({
el: $('.js-categories-view'),
initialize: function () {
...
}
...
templates: {
'category-template': _.template($('#js-category-template').html())
},
});
And if page haven't element $('.js-categories-view'), code like: new CategoriesView(); it will not be called and initialize not be called too.
But what about templates section?
_.template($('#js-category-template').html()) always called and I get the error:
Uncaught TypeError: Cannot read property 'length' of undefined
Because $('#js-category-template') doesn't present on page and and I don't want store template html on page where this View not needed?
You can check if the needed element present on the current page like this:
if( $('.js-categories-view').length ){
new CategoriesView();
}
And if you want to prevent error when calling the _.template() function, you also need to move the definition of the templates object into the initialize method of the view like follows:
var CategoriesView = Backbone.View.extend({
el: $('.js-categories-view'),
initialize: function () {
this.templates = {
'category-template': _.template($('#js-category-template').html())
};
...
}
});
Thanks all! It's good solution. But eventually I implement this:
$(function () {
if (!$('.js-categories-view').length) {
return;
}
var CategoriesPageModel = Backbone.Model.extend({
...
to not to think about issues like this. But I think thant better solution can be found

Create a generic class to bind knockout object with pages

I am bit new to knockout and jquery mobile, There was a question which is already answered, I need to optimize the PageStateManager class to use generic bindings, currently PageStateManager can only use for one binding,I would really appreciate if someone can guide me to create a generic class to manage page states with knockout bindings Heere is the working code,http://jsfiddle.net/Hpyca/14/
PageStateManager = (function () {
var viewModel = {
selectedHospital: ko.observable()
};
var changePage = function (url, viewModel) {
console.log(">>>>>>>>" + viewModel.id());
$.mobile.changePage(url, {viewModel: viewModel});
};
var initPage = function(page, newViewModel) {
viewModel.selectedHospital(newViewModel);
};
var onPageChange = function (e, info) {
initPage(info.toPage, info.options.viewModel);
};
$(document).bind("pagechange", onPageChange);
ko.applyBindings(viewModel, document.getElementById('detailsView'));
return {
changePage: changePage,
initPage: initPage
};
})();
Html
<div data-role="page" data-theme="a" id="dashBoardPage" data-viewModel="dashBoardViewModel">
<button type="button" data-bind="click: goToList">DashBoard!</button>
</div>
New dashboard model
var dashBoardViewModel = function() {
var self = this;
self.userName = ko.observable('Welcome! ' + "UserName");
self.appOnline = ko.observable(true);
self.goToList = function(){
//I would like to use PageStateManager here
// PageStateManager.changePage($("#firstPage"),viewModel);
ko.applyBindings(viewModel,document.getElementById("firstPage"));//If I click Dashbord button multiple times it throws and multiple bind exception
$.mobile.changePage($("#firstPage"));
}
}
ko.applyBindings(dashBoardViewModel,document.getElementById("dashBoardPage"));
update url : http://jsfiddle.net/Hpyca/14/
Thank you in advance
I would probably go for creating a NavigationService which only handles changing the page and let knockout and my view models handle the state of the pages.
An simple example of such a NavigationService could be:
function NavigationService(){
var self = this;
self.navigateTo = function(pageId){
$.mobile.changePage($('#' + pageId));
};
}
You could then, in your view models just call it when you want it to navigate to a new page. One example would be upon selection of a hospital (which could be done either via a selection function or by manually subscribing to changes to the selectedHospital observable):
self.selectHospital = function(hospital){
self.selectedHospital(hospital);
navigationService.navigateTo('detailsView');
};
Other than the call to the navigationService to navigate, it's just ordinary knockout to keep track of which viewmodel should be bound where. A lot easier than having jquery mobile keeping track of which viewmodel goes where, if you ask me.
I have updated your jsfiddle to show a sample of how this could be done, making as few changes as possible to the HTML code. You can find the updated fiddle at http://jsfiddle.net/Hpyca/15/

Calling jQuery plugin public function within plugin

I know, there are quite a few examples on the Web, but finding real one out of them all is tough for beginner. So I want to create jQuery plugin with public methods. Example code:
(function($) {
$.fn.peel = function(options) {
var defaults = {
};
var settings = $.extend({},defaults, options);
this.public = function() {
alert("public");
};
var private = function() {
alert("private");
}
return this.each(function() {
//this.public();
private();
});
};
})(jQuery);
As I found, this is the way to make public function, which could be called like this :
var peel = $('img').peel();
peel.public();
So far it works as expected - public() can be called. But what if i want to call that function within my plugin? I commented out in this.each() because it does not work. How can i achieve that?
One way to create publicly accessible methods within your plugins is to use the jQuery UI widget factory. This is the framework that jQuery UI uses for all of it's supported UI widgets. A quick example would look like this:
(function( $ ) {
$.widget( "something.mywidget", {
// Set up the widget
_create: function() {
},
publicFunction: function(){
//...
}
});
}( jQuery ) );
var $w = $('#someelement').mywidget();
$w.mywidget('publicFunction');

How do I override / extend a prototype.js class in a completely seperate .js file

I have a prototype.js class that I would like to extend to both add some new functions and override a couple of the functions already there.
in the example below I would like to add initAutocompleteNew and edit initAutocomplete to alert "new".
Varien.searchForm = Class.create();
Varien.searchForm.prototype = {
initialize : function(form, field, emptyText){
this.form = $(form);
this.field = $(field);
this.emptyText = emptyText;
Event.observe(this.form, 'submit', this.submit.bind(this));
Event.observe(this.field, 'focus', this.focus.bind(this));
Event.observe(this.field, 'blur', this.blur.bind(this));
this.blur();
},
//////more was here
initAutocomplete : function(url, destinationElement){
alert("old");
},
}
someone suggested but that doesn't work I think it's jQuery?
$.extend(obj_name.prototype, {
newfoo : function() { alert('hi #3'); }
}
This article should help out: http://prototypejs.org/learn/class-inheritance
It looks like you're defining your classes the 'old' way as described in the first example on that page. Are you using 1.7?
Assuming you are using 1.7, if you wanted to override or add methods to your class, you can use Class.addMethods:
Varien.searchForm.addMethods({
initAutocomplete: function(url, destinationElement) {
// Your new implementation
// This will override what was previously defined
alert('new');
},
someNewMethod: function() {
// This will add a new method, `someNewMethod`
alert('someNewMethod');
}
});
Here's a fiddle: http://jsfiddle.net/gqWDC/

Categories

Resources