mcpField
F
frontend-js

frontend-js

github.com/ahmed-lakosha開発7682 回インストール31 週間前に更新
リポジトリ

frontend-js について

Odoo 14~19のフロントエンドJavaScript開発向けリファレンススキルです。バージョンに応じたWebサイトテーマ、Owlコンポーネント、翻訳、Bootstrap移行のパターンを示します。

主な機能

  1. 01Odooのバージョン別ガイダンス
  2. 02publicWidgetによるWebサイトテーマ
  3. 03Owlコンポーネントのパターン
  4. 04JavaScriptの翻訳方法
  5. 05Bootstrap 4から5への移行

活用シーン

  1. 01OdooのWebサイトテーマに操作機能を実装
  2. 02Odooのバージョンに合わせてフロントエンドコードを調整
  3. 03Odoo 16以降向けにBootstrapクラスを移行

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/ahmed-lakosha/odoo-plugins --skill frontend-js

インストール後、Claude Code で/frontend-jsを入力して読み込まれたか確認します。

詳細

Odoo フロントエンド JavaScript のパターン

重要なルール

  1. ウェブサイトテーマ:publicWidget フレームワークのみを使用してください。Owl やバニラ JavaScript は使用しないでください
  2. JS モジュール:すべてのファイルの先頭に /** @odoo-module **/ を記述してください
  3. インライン JS/CSS の禁止:必ず static/src/js/ と static/src/scss/ にファイルを分けてください
  4. Bootstrap:Odoo 16 以降では v5.1.3 を使用してください(Tailwind は使用しないでください)
  5. 翻訳:静的な JS ラベルには、定義時に _t() を使用してください

バージョンの判別

OdooBootstrapOwlJavaScript
144.x—ES6+
154.xv1ES6+
165.1.3v1ES2020+
175.1.3v2ES2020+
18-195.1.3v2ES2020+

パス(odoo17/ → v17)、マニフェストのバージョンフィールド、または設定ファイルから判別してください。


publicWidget パターン(テーマでは必須)

用途:ウェブサイトのインタラクション、テーマ機能、アニメーション、フォーム

/** @odoo-module **/

import publicWidget from "@web/legacy/js/public/public_widget";

publicWidget.registry.MyWidget = publicWidget.Widget.extend({
    selector: '.my-selector',
    disabledInEditableMode: false,  // Allow in website builder

    events: {
        'click .button': '_onClick',
        'change input': '_onChange',
        'submit form': '_onSubmit',
    },

    /**
     * CRITICAL: Check editableMode for website builder compatibility
     */
    start: function () {
        if (!this.editableMode) {
            this._initializeAnimation();
            this._bindExternalEvents();
        }
        return this._super.apply(this, arguments);
    },

    _initializeAnimation: function () {
        this.$el.addClass('animated');
    },

    _bindExternalEvents: function () {
        $(window).on('scroll.myWidget', this._onScroll.bind(this));
        $(window).on('resize.myWidget', this._onResize.bind(this));
    },

    _onClick: function (ev) {
        ev.preventDefault();
        if (this.editableMode) return;
        // Handler logic
    },

    /**
     * CRITICAL: Clean up event listeners to prevent memory leaks
     */
    destroy: function () {
        $(window).off('.myWidget');  // Remove namespaced events
        this._super.apply(this, arguments);
    },
});

export default publicWidget.registry.MyWidget;
要点
  1. アニメーションやインタラクションの前に、必ず this.editableMode を確認してください
  2. disabledInEditableMode: false にすると、ウィジェットがウェブサイトビルダーで動作します
  3. 必ず destroy() でイベントリスナーをクリーンアップしてください
  4. ウェブサイトテーマでは、Owl やバニラ JavaScript を使用しないでください
  5. クリーンアップを容易にするため、名前空間付きイベント(.myWidget)を使用してください
マニフェストへの追加
'assets': {
    'web.assets_frontend': [
        'module_name/static/src/js/my_widget.js',
    ],
}

Owl コンポーネントのパターン

Odoo 17(Owl v1)
/** @odoo-module **/

import { Component, useState } from "@odoo/owl";
import { registry } from "@web/core/registry";

class MyComponent extends Component {
    setup() {
        this.state = useState({ items: [], loading: false });
    }

    async willStart() {
        await this.loadData();
    }
}

MyComponent.template = "module_name.MyComponentTemplate";
registry.category("public_components").add("MyComponent", MyComponent);
Odoo 18-19(Owl v2 — 破壊的変更)
/** @odoo-module **/

import { Component, useState } from "@odoo/owl";

class MyComponent extends Component {
    static template = "module_name.MyComponentTemplate";  // Static property
    static props = {
        title: { type: String, optional: true },
        items: { type: Array },
    };

    setup() {
        this.state = useState({ selectedId: null });
    }
}
XML テンプレート
<template id="MyComponentTemplate" name="My Component">
    <div class="my-component">
        <h3 t-if="props.title"><t t-esc="props.title"/></h3>
        <ul>
            <li t-foreach="props.items" t-as="item" t-key="item.id">
                <t t-esc="item.name"/>
            </li>
        </ul>
    </div>
</template>

翻訳(_t)のベストプラクティス

正しい方法 — 定義時にラップする
/** @odoo-module **/
import { _t } from "@web/core/l10n/translation";

// Static labels wrapped where defined
const MONTHS = [
    {value: 1, short: _t("Jan"), full: _t("January")},
    {value: 2, short: _t("Feb"), full: _t("February")},
    // ...
];

const STATUS_LABELS = {
    draft: _t("Draft"),
    pending: _t("Pending"),
    approved: _t("Approved"),
};
誤った方法 — 実行時のラッパーは機能しません
// WRONG: Strings without _t() at definition
const MONTHS = [{value: 1, label: "Jan"}]; // NOT found by PO extractor!

// WRONG: Variable passed to _t() at runtime
translateLabel(key) {
    return _t(key);  // PO extractor can't find string literals
}
_t() の使用場面
_t() を使用する_t() を使用しない
JS 配列/オブジェクト内の静的ラベルXML テンプレート内の静的テキスト(自動翻訳されます)
JS 定数内のエラーメッセージ実行時に渡される動的変数
JS で定義されたユーザー向け文字列.xml ファイル内のハードコードされた文字列

Bootstrap 4 → 5 の移行(Odoo 14/15 → 16 以降)

クラスの置き換え
Bootstrap 4Bootstrap 5
ml-*ms-* (margin-start)
mr-*me-* (margin-end)
pl-*ps-* (padding-start)
pr-*pe-* (padding-end)
text-lefttext-start
text-righttext-end
float-leftfloat-start
float-rightfloat-end
form-groupmb-3
custom-selectform-select
closebtn-close
badge-*bg-*
font-weight-boldfw-bold
sr-onlyvisually-hidden
no-guttersg-0
データ属性
Bootstrap 4Bootstrap 5
data-toggledata-bs-toggle
data-targetdata-bs-target
data-dismissdata-bs-dismiss
削除されたクラス(代替手段を探してください)
  • form-inline → グリッド/フレックスのユーティリティを使用してください
  • jumbotron → ユーティリティを使って再現してください
  • media → フレックスのユーティリティと d-flex を使用してください

SCSS の Bootstrap オーバーライド

ファイル:static/src/scss/bootstrap_overridden.scss バンドル:web._assets_frontend_helpers

@import "~bootstrap/scss/functions";
@import "~bootstrap/scss/variables";

$spacer: 1rem !default;
$border-radius: 0.25rem !default;
$border-radius-lg: 0.5rem !default;
$box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .15) !default;

すべてのオーバーライドに !default フラグを使用してください。


バージョン固有の注意事項

Odoo 17
  • Owl v1:テンプレートは別のプロパティとして指定します
  • スニペットの登録:シンプルな XPath を使用します
  • インポート:@web/legacy/js/public/public_widget
Odoo 18-19
  • Owl v2:静的テンプレート、props の検証
  • スニペットグループが必須です
  • ウェブサイトビルダー:プラグインアーキテクチャ(Odoo 19)
  • 破壊的変更:コントローラーの type='json' → type='jsonrpc'

コメント