Adding an Owl component to an existing view in Odoo 16 - odoo

I have an existing Odoo 16 application with a working view that contains the following inside a Form view:
<sheet>
<notebook>
<page name="plan_vehicles" string="Vehicles">
<field name="vehicle_time_ids"/>
</page>
</notebook>
</sheet>
I want to add another page to the notebook that will display an Owl component.
I have tried to extract the required code from the official tutorial, so I have the following code:
templates.xml
<odoo>
<data>
<template id="transport.stops" name="Awesome T-Shirt thank you">
<html>
<head>
<t t-call-assets="transport.assets"/>
</head>
<body>
</body>
</html>
</template>
</data>
main.js:
/** #odoo-module **/
import { browser } from "#web/core/browser/browser";
import { mount } from "#odoo/owl";
import { Stops } from "./stops";
// The following code ensures that owl mount the component when ready.
// `templates` contains templates contained in the bundles.
//
// In the mount options, it's also possible to add other interresting
// configuration: https://github.com/odoo/owl/blob/master/doc/reference/app.md#configuration
import { templates } from "#web/core/assets";
owl.whenReady( () => {
mount(Stops, document.body, { templates, dev: true });
});
stops.js:
/** #odoo-module **/
import { Component, useState } from "#odoo/owl";
export class Stops extends Component {
static template = "transport.stops";
}
stops.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<t t-name="transport.stops" owl="1">
<div class="p-3">
hello world
</div>
</t>
</templates>
manifest.xml:
'assets': {
'web.assets_backend': [
'transport/static/src/*.**',
],
'web.assets_qweb': [
'transport/static/src/*.xml'
],
'transport.assets': [
# bootstrap
('include', 'web._assets_helpers'),
'web/static/src/scss/pre_variables.scss',
'web/static/lib/bootstrap/scss/_variables.scss',
('include', 'web._assets_bootstrap'),
'web/static/src/libs/fontawesome/css/font-awesome.css', # required for fa icons
'web/static/src/legacy/js/promise_extension.js', # required by boot.js
'web/static/src/boot.js', # odoo module system
'web/static/src/env.js', # required for services
'web/static/src/session.js', # expose __session_info__ containing server information
'web/static/lib/owl/owl.js', # owl library
'web/static/lib/owl/odoo_module.js', # to be able to import "#odoo/owl"
'web/static/src/core/utils/functions.js',
'web/static/src/core/browser/browser.js',
'web/static/src/core/registry.js',
'web/static/src/core/assets.js',
'transport/static/src/**/*',
],
},
the import of the template.xml file in the data list.
I think I am missing two things:
how does the Owl template stops.xml relate to the template in templates.xml and
how to add the the component/template to a new page in my notebook so that I can see the 'hello world'.

Related

Registering Vue components in html files

I'm having trouble using Vue.js components in HTML files.
Mainly I have a problem with registering the component and using it in the html file.
In general, I'd like to register a component and use it anywhere in the code. The current code that I took from the original Vue.js website works so that the component is added to the application right away.
index.html:
<body>
<div id="app">
<header></header>
<nav></nav>
<main></main>
<footer> </footer>
</div>
</body>
</html>
<script type="importmap">
{
"imports": {
"vue": "https://unpkg.com/vue#3/dist/vue.esm-browser.js"
}
}
</script>
<script type="module">
import { createApp } from 'vue'
import MyComponent from './header.js'
createApp(MyComponent).mount('#app')
</script>
Header.js:
export default {
data() {
return { count: 0 }
},
template: `<div>count is {{ count }}</div>`
}
Then the created component in another file actually works, but it is added automatically to the application.
How could I register this component and put it in the code where I want?

Bpmn.io custom panel properties doesn't show the field

I have tried to use the Bpmn.io modeler plus panel properties in Vue3 and I followed exactly what they have described in this example in Bpmn.io official examples. But it seems doesn't work properly in Vue (I guess Vuejs is the reason), and I don't know why. I can see the custom group but inside it is completely empty.
These are my codes:
main.js
import { createApp } from 'vue'
import App from './App.vue'
import '../node_modules/bpmn-js/dist/assets/bpmn-js.css'
import '../node_modules/bpmn-js/dist/assets/diagram-js.css'
import '../node_modules/bpmn-js/dist/assets/diagram-js.css'
import '../node_modules/bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css'
import '../node_modules/bpmn-js-properties-panel/dist/assets/properties-panel.css'
createApp(App).mount('#app')
App.vue
<template>
<div>
<div id="js-canvas"></div>
<div id="js-properties-panel"></div>
</div>
</template>
<script>
import BpmnModeler from "bpmn-js/lib/Modeler";
import {
BpmnPropertiesPanelModule,
BpmnPropertiesProviderModule,
} from "bpmn-js-properties-panel";
import magicPropertiesProviderModule from "./provider/magic/";
import magicModdleDescriptor from "./descriptors/magic";
export default {
mounted() {
const diagram = `
<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd" id="sample-diagram" targetNamespace="http://bpmn.io/schema/bpmn">
<bpmn2:process id="Process_1" isExecutable="false">
<bpmn2:startEvent id="StartEvent_1"/>
</bpmn2:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds height="36.0" width="36.0" x="412.0" y="240.0"/>
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>
`;
const bpmnModeler = new BpmnModeler({
container: "#js-canvas",
propertiesPanel: {
parent: "#js-properties-panel",
},
additionalModules: [
BpmnPropertiesPanelModule,
BpmnPropertiesProviderModule,
magicPropertiesProviderModule,
],
moddleExtensions: {
magic: magicModdleDescriptor,
},
});
bpmnModeler.importXML(diagram);
},
};
</script>
I solved my problem
I found out that I need to configure your compiler to recognize JSX properly.
That's the solution:
1- Adding "#babel/plugin-transform-react-jsx": "^7.18.6" as a devDependency in package.json
2- Adding plugins config to the babel.config.js
module.exports = {
presets: [
'#vue/cli-plugin-babel/preset'
],
plugins: [
[
'#babel/plugin-transform-react-jsx',
{
throwIfNamespace: false,
runtime: 'automatic',
importSource: '#bpmn-io/properties-panel/preact',
}
]
]
}

Font Awesome embed code not working in project generated with Vue CLI

I created a default Vue project with the Vue CLI, and got an embed code sent to my email for Font Awesome 5. I added that code to my project index.html in the public folder.
<head>
<script src="https://use.fontawesome.com/8e1c33adc2.js"></script>
</head>
I'm using this in a component template:
<i class="fas fa-trash"></i>
It just shows up as a box.
Do I have to do something special to get the embed code to work in my Vue component, like adding it to main.js?
I have had issues with font-awesome with vue. The solution for my problem was to use vue-fontawesome components.
For example, I used font-awesome the following way
import { FontAwesomeIcon } from '#fortawesome/vue-fontawesome'
import { faAngleDown } from '#fortawesome/free-solid-svg-icons'
import { faAngleUp } from '#fortawesome/free-solid-svg-icons'
export default {
name: 'Timer',
props: {
msg: String
},
components:{
FontAwesomeIcon
},
data: function(){
return {
selected_interval: null,
intervalID: null,
buttonText: "Start",
isStart: true,
isStop: false,
toggleAngle: faAngleDown,
},
methods: {
dropdown_toggle: function(event) {
event.stopPropagation()
let dropdown = document.querySelector('#pomodoro-dropdown');
dropdown.classList.toggle("is-active")
if(this.toggleAngle == faAngleDown){
this.toggleAngle = faAngleUp
}
else{
this.toggleAngle = faAngleDown
}
}
}
and used the componenent-
<font-awesome-icon :icon="toggleAngle" />
hope this helps.
I got it working by logging into Font Awesome and using the free kit code from https://fontawesome.com/kits.
All I needed was this in the head section of index.html:
<head>
<script src="https://kit.fontawesome.com/[kit code].js" crossorigin="anonymous"></script>
</head>
you have to add the css file of font-awesome.you can open developer tools and see there is no class with the <i></i>

How to access other module method(outside VueJs) in component markup?

I have one external module as following:
const externalModule = {
thisMethodWantToUseInMarkup: () =>{
alert("success");
}
}
export default externalModule
i want to access thisMethodWantToUseInMarkup from component markup(from button A in following code).
<template lang="html">
<div class="bg-white">
<button #click="externalModule.thisMethodWantToUseInMarkup()">Button A</button> <!-- is it possible like this directly -->
</div>
</template>
what is the best practice to do this ?
Note: - I don't want to import global module in every component.
Use simple import in your script section of the view component (if you're using the default .vue files), or inside your javascript file. Something similar to:
<template lang="html">
<div class="bg-white">
<button #click="customMethod"> <!-- call your internal method -->
Button A
</button> <!-- is it possible like this directly -->
</div>
</template>
<script>
import { externalModule } from './externalModule'
export default {
name: 'mainComponent',
methods: {
customMethod() {
externalModule.thisMethodWantToUseInMarkup()
}
}
}
</script>
Using internal method you won't bind user interaction with a specific implementation, and therefore switching the files/logic for it will simply mean changing the import file. This is useful for testing purposes in where you could dynamically load specific files based on environment for example.

How to define a template fom the `text/ng-template` source in angular2?

I am trying to apply the html from my internal text/ng-template script tag. but it's fails to work. how to apply html from the script tag?
Here is my code and html:
js part :
//our root app component
import {Component} from 'angular2/core'
#Component({
selector: 'my-app',
providers: [],
templateUrl: "template.html", //this is the id.
directives: []
})
export class App {
public title = "My Title";
private userName = "Test Name";
constructor() {
this.name = 'Angular2'
}
}
HTML part :
<body>
<my-app>loading...</my-app>
//template declared
<script type="text/ng-template" id="template.html">
<h2>{{title}}</h2>
<div>
<h2>Hello {{name}}</h2>
<h2>{{userName}}</h2>
</div>
</script>
</body>
I am getting a error :
Failed to load template.html
What is the correct way to use it?
Unfortunately, this is not, nor will be, supported in Angular 2 :\ https://github.com/angular/angular/issues/6126