Skip to Content

آموزش کامل و کاربردی PublicWidget در Odoo

راهنمای گام به گام برای درک، ساخت و استفاده از publicWidget در پروژه‌های Odoo

اگه تا حالا با توسعه فرانت‌ اند تو Odoo​ کار کرده باشی، حتما اسم publicWidget​ به گوشِت خورده. publicWidget​ در واقع همون روشی بود (و هنوز هم هست) که اودو برای کنترل رفتار صفحات سایتش استفاده میکنه.

یعنی مثلا وقتی میخوای تو فرم ثبت نام کاربر، یه اعتبارسنجی برای شماره موبایل بنویسی، یا یه مودال خاص باز کنی، یا حتی رو دکمه ها یه رفتار سفارشی بندازی، دقیقا publicWidget​ اون ابزار جادویی بود که باید سراغش میرفتی.

الان با اومدن OWL​ و سیستم جدیدش، خیلی ها فکر میکنن دیگه publicWidget​ منقرض شده، ولی هنوزم بخش بزرگی از ماژول های وب و سایت اودو روی این سیستم قدیمی اما قدرتمند کار میکنن.

پس اگه می‌خوای واقعا فرانت اند اودو رو بفهمی، باید publicWidget​ رو مثل کف دستت بشناسی.

publicWidget​ دقیقا چیه؟

publicWidget​ یه کلاس جاوا اسکریپتیه که از ساختار قدیمی اودو به اسم Widget​ میاد.

اودو با این سیستم یه راه ساده برای ساخت رفتارهای قابل تکرار و ماژولار تو بخش فرانت‌اند ایجاد کرده بود.

هر publicWidget​ در واقع یه کلاس جاوا اسکریپتیه که به یه المنت خاص در صفحه (بر اساس selector​) وصل میشه و رویدادها (event​ ها) و رفتارهاش رو کنترل میکنه.

به زبان ساده‌تر:

اگه بخوای بگی "وقتی کاربر روی فیلد شماره موبایل کلیک کرد یا blur​ شد، یه اتفاق خاص بیفته"، publicWidget​ دقیقا این کار رو برات انجام میده.

ساختار اصلی publicWidget

هر publicWidget​ به این شکل تعریف میشه:

/** @odoo-module **/ import publicWidget from "@web/legacy/js/public/public_widget"; publicWidget.registry.MyWidgetName = publicWidget.Widget.extend({ selector: '.my-selector', events: { 'click .my-button': '_onClickButton', }, start: function () { console.log("Widget started!"); }, _onClickButton: function (ev) { alert("Button clicked!"); } });

بیا قدم به قدم بررسیش کنیم 👇

selector

اینجا مشخص میکنی ویجت روی کدوم بخش از صفحه سوار (mount​) بشه. این selector​ به this.target  مپ (map​) میشه.

مثلاً اگه selector​ برابر .my-form​ باشه، این ویجت فقط روی عناصری که اون کلاس رو دارن اجرا میشه.

events

یه آبجکت از لیست رویدادهاست که کلیدش رویداد (مثل click, change, blur​) و مقدارش اسم تابع هندلر هست. به این ساختار event mapping میگن که هر event​ روی selector به اصطلاح bind​ میشه

مثلاً click .my-button​ یعنی وقتی داخل المنت انتخاب‌شده، یه عنصر با کلاس .my-button​ کلیک شد، تابع _onClickButton​ اجرا بشه.

start()

یه lifecycle hook که وقتی ویجت راه‌اندازی میشه اجرا میشه.

اینجا معمولاً مقداردهی اولیه، انتخاب المنت ها یا تنظیم لیسنرها انجام میشه.

ویجت ها هوک های دیگه ای هم دارن:

willStart()​: قبل از start()​ اجرا میشه و می تونه async​ باشه و برای درخواست داده از سرور قبل از render​ استفاده میشه.

destroy()​: قبل از حذف از DOM​ اجرا میشه و برای آزادسازی منابع یا listener​ها قابل استفادست.

متد خصوصی _onClickButton

یه event handler​ که event​ رو هندل می کنه. یعنی وقتی event​ رخ میده این اجرا میشه.

مثال واقعی — اعتبارسنجی شماره موبایل با پلاگین intlTelInput

توی این مثال فرض شده پلاگین رو به پروژه اضافه کردیم. حالا فرض کن یه فرم داری برای گرفتن شماره موبایل کاربر، و می‌خوای مطمئن بشی شماره وارد شده معتبره.

کد زیر دقیقا همون کاریه که publicWidget​ به راحتی انجام میده:

/** @odoo-module */ import publicWidget from "@web/legacy/js/public/public_widget"; publicWidget.registry.PhoneInputValidation = publicWidget.Widget.extend({ selector: '#mobile', events: { 'blur': '_onBlur', 'change': '_reset', 'keyup': '_reset' }, start: function () { this.input = this.el; this.form = this.input.closest('form'); this._onFormSubmit = this._onFormSubmit.bind(this); this.iti = window.intlTelInput(this.input, { initialCountry: "us", separateDialCode: true, nationalMode: false, autoPlaceholder: 'aggressive', formatOnDisplay: true, }); if (this.form) { this.form.addEventListener('submit', this._onFormSubmit); } }, _onBlur: function () { this._reset(); if (this.input.value.trim()) { if (this.iti.isValidNumber()) { this.input.classList.add("is-valid"); } else { this.input.classList.add("is-invalid"); } } }, _reset: function () { this.input.classList.remove("is-invalid", "is-valid"); }, _onFormSubmit: function (ev) { ev.preventDefault(); const mobile_input = document.querySelector('input[name="formated_mobile"]'); this._reset(); if (!this.iti.isValidNumber()) { this.input.classList.add("is-invalid"); return; } mobile_input.value = this.iti.getNumber(); this.form.submit(); } });

اینجا اتفاقی که میفته اینه که:

  • وقتی کاربر روی فیلد موبایل کلیک کنه یا blur​ کنه، شماره بررسی میشه.
  • اگه شماره معتبر نباشه، کلاس is-invalid​ به input​ اضافه میشه.
  • وقتی فرم ارسال میشه، شماره نهایی فرمت شده تو فیلد formated_mobile​ ذخیره میشه.

خیلی تمیز، جدا از بقیه کدها و قابل استفاده مجدد.

چرا هنوز هم publicWidget​ مهمه؟

با اینکه OWL​ وارد دنیای جدید اودو شده، اما publicWidget​ هنوز در بخش‌هایی از Website، eCommerce، Portal و Blog​ به شدت استفاده میشه.

مزیت بزرگش اینه که بدون نیاز به تغییر ساختار قالب (QWeb​) می‌تونی فقط با یه فایل جاوا اسکریپت رفتار صفحه رو کنترل کنی.

مزایا:

  • ساده و سریع برای پروژه‌های کوچک
  • نیاز نداشتن به سیستم Component
  • قابل اجرا بدون تغییر ساختار DOM
  • پشتیبانی از تمام قالب‌های QWeb​ قدیمی

معایب:

  • ساختار قدیمی و کمتر ماژولار
  • دشوارتر برای تست و دیباگ
  • وابسته به DOM​ ثابت
  • ناسازگار با ساختار OWL​ و reactive state

نکاتی که در استفاده از publicWidget​ باید رعایت کنی

  • همیشه ویجت رو در مسیر static/src/js/​ بذار تا اودو به صورت خودکار لودش کنه.
  • از دستور /** @odoo-module */ ​ در ابتدای فایل استفاده کن تا سیستم ماژول اودو بفهمه این فایل مدرن هست.
  • اگه چند ویجت داری، نام‌گذاری Registry‌​ ها رو دقیق انجام بده تا تداخلی پیش نیاد.
  • اگه رفتار وابسته به template​ خاصی داری، selector​ رو محدود به اون فرم کن تا در کل سایت اجرا نشه.

تفاوت publicWidget​ با OWL

در OWL​، همه چیز بر اساس Component​ طراحی شده، یعنی به جای extend​ کردن Widget​، شما یه Component​ می‌سازید و اون رو یا با mount()​ به یه بخش از DOM​ وصل می‌کنید، یا با <t t-component="MyComponent"/>​ مستقیماً داخل قالب QWeb​ میذارید.

اما در publicWidget​ شما فقط رفتار رو به المنت موجود در صفحه اضافه می‌کنید، بدون اینکه کامپوننت جدیدی بسازید.

بنابراین publicWidget​ بیشتر برای اسکریپت‌های رفتاری و سبک مناسبه، در حالی که OWL​ برای اپلیکیشن‌های پویا و پیچیده طراحی شده.

جمع‌بندی

publicWidget​ هنوز یکی از پایه‌های اصلی توسعه فرانت‌اند در Odoo​ محسوب میشه.

حتی اگر هدف نهاییت کار با OWL​ باشه، درک publicWidget​ باعث میشه درک بهتری از چرخه حیات، DOM​ و تعاملات کاربری در اودو پیدا کنی.

برای پروژه‌هایی مثل:

  • فرم‌های ساده
  • کنترل رویدادها
  • اعتبارسنجی‌های درجا
  • نمایش پیام‌ها یا مودال‌های سبک

هنوز publicWidget​ یه گزینه عالی و سریع به حساب میاد.

در آینده یه مقاله درباره پیاده سازی همین ویجت با OWL​ مینویسم و در اختیارتون میذارم. 

راهنمای کامل عبور از چالش های رایج در پیاده‌سازی Odoo
از سردرگمی تا بهره‌وری؛ تجربه‌ای واقعی از یکپارچه‌سازی موفق Odoo