I have created a website template in ODOO V8:
<template id="assets_frontend" inherit_id="website.assets_frontend" name="MyTemplate">
<xpath expr="." position="inside">
<script type="text/javascript" src="/my_module/static/src/js/main.js"></script>
</xpath>
</template>
<template id="my_template">
<script type="text/javascript" src="/my_module/static/src/js/main.js"/>
<div>
<table>
<tr>
<td>Email: <input type="text" id="email"/></td>
</tr>
<tr>
<td colspan="3">
<input type="button" value="Submit" onclick="submitEmail();"/>
</td>
</tr>
</table>
</div>
</template>
And the contents in main.js file are:
$(document).ready(function () {
"use strict";
function submitEmail() {
var self = this;
var website = openerp.website;
var Users = new openerp.website.Model('res.users');
// ...
}
})();
But on clicking the submit button in the template it shows the following error in the browser console.
Uncaught ReferenceError: openerp is not defined
I need to access the ODOO models and methods in it from the main.js file. How can I solve the above error or is there any way I can access the models and methods defined in ODOO classes from a javascript file?
This error is not in the base modules(like website_sale) in ODOO and the error is only in new modules I have created.
inside $(document).ready you can't access openerp .
In the js file create a method same name as your module(not model) and pass two parameter instance and module
Now in the method you can access the module using instance of openerp like:
function my_module(instance, module){
module = instance.point_of_sale;
var QWeb = instance.web.qweb;
_t = instance.web._t;
var OrderSuper = module.ProductListWidget;
}
You need read this document https://www.odoo.com/documentation/8.0/reference/javascript.html and take attention on "Subclassing Widget". This is an example of a module in Odoo. You have to program something like that example.
Related
I am generating html table from Javascript and assign as InnerHTML to a div tag, but its giving an error:
"Uncaught TypeError: Cannot set property 'innerHTML' of null"
<html>
<body>
<div class="fieldlist-vertical-title" style="color:white;left:0px;display:none;" id="rosterlegend">Some text</div>
<script>
function generateLegend()
{
var fullTable ='' fullTable='<Table><TR><Table><TR bgcolor=#FF5733><TD>MM</TD>
<TD>01:00 to 21:30</TD></TR></Table></TR></Table>'
document.getElementById('rosterlegend').innerHTML = fullTable
}
generateLegend();
</script>
</body>
</html>
Error : Uncaught TypeError: Cannot set property 'innerHTML' of null
Try changing to something like this, so we ensure the HTML DOM has completed loading first.
Use ES6 template string instead of plain strings!
document.addEventListener('DOMContentLoaded', () => {
generateLegend();
});
function generateLegend() {
fullTable = `<Table>
<TR>
<Table>
<TR bgcolor=#FF5733>
<TD>MM</TD>
<TD>01:00 to 21:30</TD>
</TR>
<TR bgcolor=#FFFFFF>
<TD>EVVV</TD>
<TD>09:00 to 05:30</TD>
</TR>
</Table>
</TR>
</Table>`;
document.getElementById('rosterlegend').innerHTML = fullTable;
}
<div id="rosterlegend">
<div>
Removes new lines and extra spaces in the HTML String.
Rest of your code works fine!
However it is not a god practice.
Ideally you have to wait for the window to be loaded.
window.onload(){
generateLegend();
}
function generateLegend() {
var fullTable = " <Table><TR><Table><TR bgcolor=#FF5733><TD>MM</TD><TD>01:00 to 21:30</TD></TR><TR bgcolor=#FFFFFF><TD>EVVV</TD><TD>09:00 to 05:30</TD></TR></Table></TR></Table>";
document.getElementById('rosterlegend').innerHTML = fullTable;
}
generateLegend();
<div id="rosterlegend">Some text</div>
Your issue is that you are trying to access your div with the id of "rosterlegend" before the DOM has loaded. This means that when your javascript tries to access your element it cannot. One way you can fix this is by adding the load or DOMContentLoaded event listener to your element, where the function will fire once your HTML (including images if you use the load event) and window has loaded. This way your javascript will know about your HTML.
See working example below:
function generateLegend() {
var fullTable = " <Table><TR><Table><TR bgcolor=#FF5733><TD>MM</TD><TD>01:00 to 21:30</TD></TR><TR bgcolor=#FFFFFF><TD>EVVV</TD><TD>09:00 to 05:30</TD></TR></Table></TR></Table>";
document.getElementById('rosterlegend').innerHTML = fullTable;
}
window.addEventListener("load", generateLegend); // call your function when the window has loaded
<div id="rosterlegend"></div>
I'm trying to create a simple javascript code in odoo 10. So Under myModule\static\src\js folder I added a test.js file containing this code:
alert("it works!!");
And Under myModule\views I added an xml file containing this code:
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<template id="assets_backend" name="solixy assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<script type="text/javascript" src="/solixyProject/static/src/js/test.js"></script>
</xpath>
</template>
</data>
And it works fine when I update my module and refresh odoo. Now I want this js code to be called when I press a button. So I changed js code like this:
function clickMe(){
alert("it works!!");
};
Then in my form I added this button:
<button name="test_js" string="Test Javascript File" type="object" class="btn-primary" onclick="clickMe()"/>
Now the button is shown but I don't have my alert box!!
Thank you for your help.
It looks like I'm missing many other javascript code so my method can work. We can't just add a method like this:
function clickMe(){
alert("it works!!");
};
This is the correct js code:
odoo.define('solixyProject.kanban_view', function (require){
"use strict";
var form_widget = require('web.form_widgets');
var core = require('web.core');
var _t = core._t;
var QWeb = core.qweb;
form_widget.WidgetButton.include({
on_click: function() {
if(this.node.attrs.custom === "click"){
alert("It works!!");
return;
}
this._super();
},
});
});
And this is the correct xml code:
<button string="Test Javascript Onclick Method" custom="click" />
This question helped me a lot:
Odoo javascript onclick event
How Can I create a simple widget in odoo10?? Corresponding code for
following in odoo10? HOw can i convert this code to odoo10?
local.HomePage = instance.Widget.extend({
start: function() {
this.$el.append("<div>Hello dear Odoo user!</div>");
var greeting = new local.GreetingsWidget(this);
return greeting.appendTo(this.$el);
},
});
Create Widgets and Templates in Odoo-10
Widget:
Widget is different or alternate representation to display a screen, fields and attributes in odoo.
Widget allows to change view using different rendering templates and also allows to design as you want.
Example:
widget_name.js
odoo.define('module.model_name', function(require) {
"use strict";
var Widget = require('web.Widget');
var core = require('web.core');
var Model = require('web.Model');
var QWeb = core.qweb;
var _t = core._t;
// here we are getting the value in an array.
var widget_name = Widget.extend({
//render your template
"template" : "template_name",
//initialize
init : function () {
var self = this;
this._super(parent);
//initialize values to variables
}
//Binding Events
events : {
'click .class_ex': 'method1',
'click .class_ex1': 'method2',
},
start : function() {
var self = this;
this._super(parent);
//your functionality code and logic
},
//creating functions
method1:function(){
//do something when click event fire on class_ex
},
method2:function(){
//do something when click event fire on class_ex
},
});
return widget_name;
});
You need to add this .js & .css files in odoo like this.
assets_backend.xml
<odoo>
<data>
<template id="assets_backend" inherit_id="web.assets_backend">
<xpath expr="script[last()]" position="after">
<script type="text/javascript" src="/module/static/src/js/widget_name.js"></script>
<link href="/module/static/src/css/home.css" rel="stylesheet"></link>
</xpath>
</template>
</data>
</odoo>
Design Widget Template:
Create XML and add xml:space="preserve" as argument in template tag.
t-name is name of your template that is defined in .js file and the same name is used as widget name in XML while you use it.
tmpl.xml
<?xml version="1.0"?>
<templates id="template" xml:space="preserve">
<t t-name="template_name">
<div class=”myclass”>
//design your template here
<div class=”class_ex”>
//body
</div>
<div class=”class_ex1”>
//body
</div>
</div>
</t>
</templates>
NOTE: No need to write odoo tag in tmpl.xml file.
It is important to have the template name to be the same, as given in your in .js (widget_name.js) file.
How to use a widget
Use widget by action or object button.
Shown below we add template_name to action_registry, so now we can use this name to execute using XML.
Example:
<record id="template_id" model="ir.actions.client">
<field name="name">template name</field>
<field name="tag">template_name</field>
<field name="target">new</field>
</record>
Set your "template name" in HERE
You can also write some events on your button, fields and then make a function that handles event and execute function that renders your template. Return this id (template_id) as a result when object button clicked.
You can use your widget like this also.
<field name="mobile" widget="template_name" />
I'm developing a website with Odoo v8. I want to write a snippet that its struct is load by javascript. Bellow are my code ...
Firstly, I have a snippet struct:
<template id="snippet_hello" inherit_id="website2.snippets" name="Snippet Hello">
<xpath expr="//div[#id='snippet_structure']" position="inside">
<div class="oe_snippet">
<div class="oe_snippet_thumbnail">
<img class="oe_snippet_thumbnail_img" src="/path_to_block_icon/block_icon.png"/>
<span class="oe_snippet_thumbnail_title">Hello</span>
</div>
<section class="oe_snippet_body">
<div class="oe_snippet_hello">Hello ...</div>
</section>
</div>
</xpath>
<xpath expr="//div[#id='snippet_options']" position="inside">
<div data-snippet-option-id='snippet_hello'
data-selector=".oe_snippet_hello"
data-selector-siblings="p, h1, h2, h3, blockquote, .well, .panel">
</div>
</xpath>
</template>
Then I have a little javascript code to render snippet content:
(function () {
'use strict';
var website = openerp.website;
qweb = openerp.qweb;
qweb.add_template('/path_to_snippet_qweb_template/snippet_template_filename.xml');
website.snippet.animationRegistry.hello = website.snippet.Animation.extend({
selector: ".oe_snippet_hello",
start: function(){
var $content = $(qweb.render('website.snippet_hello', {a:1}));
$content.appendTo(this.$target);
},
});
})();
Then I have a QWeb template to display my struct content (filename: snippet_template_filename.xml):
<?xml version="1.0" encoding="utf-8"?>
<templates id="template" xml:space="preserve">
<t t-name="website.snippet_hello">
<div contenteditable="false">
<p>Hello snippet</p>
<t t-esc="a"/>
</div>
</t>
</templates>
Problem is this line:
var $content = $(qweb.render('website.snippet_hello', {a:1}));
occurred error that "Template 'website.snippet_hello' not found"
I noticed that when I logged in as Admin (haven't tried another account), it works well. It just occurred error when I logged out on my browser.
Please let me your advice, thanks!
This is an old question related to an obsolete Odoo's version but answer is still relevant today (Odoo v11/12/13) :
Template Not found could occur when:
template is not loaded
template names are not equals between your js and your template's xml files. Templates names are case sensitive.
Loading a template:
Usually you save your templates in your project as /your_module/static/src/xml/snippet_template_filename.xml, and you must load this xml file on /your_module/__manifest__.py by adding:
'qweb': [
"static/src/xml/snippet_template_filename.xml",
],
or shorthand:
'qweb': [
"static/src/xml/*.xml",
],
You install/update your_module in odoo's App menu, then you can verify that your template is loaded by looking at http://localhost:8069/web/webclient/qweb?mods=your_module, it should returns your templates.
You can also look at favorite browser network inspector to check the http://localhost:8069/web/webclient/qweb?mods=[...] request and checks that in mods your_module is loaded properly.
Template can be used in your js like in this (Odoo >= v11):
odoo.define('your_module.NameOfYourJs', function (require) {
"use strict";
var QWeb = core.qweb;
[...]
var result = QWeb.render('website.snippet_hello', {a:1});
});
Note: to debug assets you can use http://localhost:8069/web?debug=assets.
Hope this helps!
I am new to programming and I am trying to wire up a couple of buttons with jQuery using Google-apps-script. I have a spread sheet and a menu added to it the opens a dialog box from HtmlService. In the dialog box I have two buttons, one closes the dialog the other executes a server function, which for now only writes "hello world to cell a1. The "close" button works perfectly, however the "update" doesn't seem to do anything. I'm not exactly sure how to debug the client-side.
<script>
$(document).ready(function(){
$("#update").click(function (){
var params = {}
params.url = $("#url").val()
params.owner = $("#owner").val()
params.type = type
google.script.run.update(params);
});
$("#close").click(function(){
// This one works. why not the "update" button???
google.script.host.close()
})
})
</script>
<title>AJAXtabs.html</title>
</head>
<body>
<div id="content">
<table border="1">
<tr>
<th><?= type ?>URL</th>
<td><input type="text" id="url" name="url"></td>
</tr>
<tr>
<th>New Owner email</th>
<td><input type="text" id="ownerEmail" name="ownerEmail"></td>
</tr>
<tr>
<td colspan="2" id="buttonRow" ><button id="update" type="button" >Update</button><button id="close" type="button">Close</button></td>
</tr>
</table>
</div>
<div id="message">
</div>
</body>
</html>
Code.gs excerpt
function update(params){
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
var row = sheet.getLastRow()
var col = sheet.getLastColumn()
sheet.getRange('a1').setValue('Hello world!!')
}
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [];
// When the user clicks on "addMenuExample" then "Menu Entry 1", the function function1 is
// executed.
menuEntries.push({name: "Set file", functionName: "fileUi"});
menuEntries.push(null); // line separator
menuEntries.push({name: "Set Folder", functionName: "folderUi"});
ss.addMenu("Setters", menuEntries);
}
function fileUi(){
var htmlApp = HtmlService.createTemplateFromFile('View template')
htmlApp.type = 'File';
SpreadsheetApp.getActiveSpreadsheet().show(htmlApp.evaluate().setHeight(300).setTitle('Chan ge Owner'));
}
function folderUi(){
var htmlApp = HtmlService.createTemplateFromFile('View template')
htmlApp.type = 'Folder'
SpreadsheetApp.getActiveSpreadsheet().show(htmlApp.evaluate());
}
Below are modified versions of your html and gs files, in which both buttons work. I believe that the only thing that needed to change was the inclusion of the jQuery library.
Debugging
Generally speaking, the best place to debug your client-side functions is in the debugger / IDE, using the techniques appropriate there. You may find some ideas that help you in this tutorial, and these answers:
Stepping through code in Google Apps Script (equivalent VBA-GAS )
How can I test a trigger function in GAS?
To support debugging, this script relies on Peter Herrmann's BetterLog library. You will need to add that to your project, by "Resources - Manage Libraries...". With it, plus the helper function included below, you will have an effective way to log operations of both your client and server side functions. (Since you're using a spreadsheet already, you can log to it... the utility will create a new tab.)
The additional use of BetterLog gives you a way to trace execution across multiple platforms or environments, with better history keeping than the built-in Logger. This example is barely scratching the surface of what that utility does - but it's enough for most purposes!
Various log messages have been left in place, to illustrate.
Example Logs
2013-07-31 00:02:17:332 -0400 000128 INFO in ready
2013-07-31 00:02:17:419 -0400 000094 INFO In html script
2013-07-31 00:02:23:508 -0400 000178 INFO in update.click
2013-07-31 00:02:24:081 -0400 000163 INFO in update (server)
2013-07-31 00:02:24:104 -0400 000186 INFO {"url":"adsfasdfsad","owner":null,"type":null}
2013-07-31 00:02:24:166 -0400 000248 INFO done update (server)
2013-07-31 00:03:14:355 -0400 000248 INFO in close.click
Code.gs
Logger = BetterLog.useSpreadsheet('--Spreadsheet-ID--');
/**
* Make BetterLogger available to client-side scripts, via
* google.script.run.log(string).
*/
function log(string) {
Logger.log(string);
}
function update(params){
Logger.log('in update (server)');
Logger.log(JSON.stringify(params));
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
var row = sheet.getLastRow()
var col = sheet.getLastColumn()
sheet.getRange('a1').setValue('Hello world!!')
Logger.log('done update (server)');
}
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [];
// When the user clicks on "addMenuExample" then "Menu Entry 1", the function function1 is
// executed.
menuEntries.push({
name: "Set file",
functionName: "fileUi"
});
menuEntries.push(null); // line separator
menuEntries.push({
name: "Set Folder",
functionName: "folderUi"
});
ss.addMenu("Setters", menuEntries);
}
function fileUi() {
var htmlApp = HtmlService.createTemplateFromFile('View template')
htmlApp.type = 'File';
var html = htmlApp.evaluate()
.setSandboxMode(HtmlService.SandboxMode.NATIVE)
.setHeight(300)
.setTitle('Change Owner');
SpreadsheetApp.getActiveSpreadsheet().show(html);
}
function folderUi() {
var htmlApp = HtmlService.createTemplateFromFile('View template')
htmlApp.type = 'Folder'
var html = htmlApp.evaluate()
.setSandboxMode(HtmlService.SandboxMode.NATIVE)
.setHeight(300)
.setTitle('Change Owner');
SpreadsheetApp.getActiveSpreadsheet().show(html);
}
View template.html
This has been restructured as per the best practices, and of course log messages are included.
<div id="content">
<table border="1">
<tr>
<th><?= type ?>URL</th>
<td><input type="text" id="url" name="url"></td>
</tr>
<tr>
<th>New Owner email</th>
<td><input type="text" id="ownerEmail" name="ownerEmail"></td>
</tr>
<tr>
<td colspan="2" id="buttonRow" >
<button id="update" type="button" >Update</button>
<button id="close" type="button">Close</button>
</td>
</tr>
</table>
</div>
<div id="message">
</div>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script>
google.script.run.log("In html script");
$(document).ready(function(){
google.script.run.log("in ready");
$("#update").click(function (){
google.script.run.log("in update.click");
var params = {}
params.url = $("#url").val()
params.owner = $("#owner").val()
params.type = type
google.script.run.update(params);
});
$("#close").click(function(){
google.script.run.log("in close.click");
google.script.host.close()
})
})
</script>