Search the Community
Showing results for 'render('.
-
Hello @ all I want to share a new module with you, which makes the creation and validation of forms easy. Take a look at the following example of a simple contact form: // A very simple example of a contactform for demonstration purposes $form = new Form('contactform'); $gender = new Select('gender'); $gender->setLabel('Gender'); $gender->addOption('Mister', '0'); $gender->addOption('Miss', '1'); $form->add($gender); $surname = new InputText('surname'); $surname->setLabel('Surname'); $surname->setRule('required'); $form->add($surname); $name = new InputText('name'); $name->setLabel('Name'); $name->setRule('required'); $form->add($name); $email = new InputText('email'); $email->setLabel('E-Mail'); $email->setRule('required'); $form->add($email); $subject = new InputText('subject'); $subject->setLabel('Subject'); $subject->setRule('required'); $form->add($subject); $message = new Textarea('message'); $message->setLabel('Message'); $message->setRule('required'); $form->add($message); $privacy = new InputCheckbox('privacy'); $privacy->setLabel('I accept the privacy policy'); $privacy->setRule('required')->setCustomMessage('You have to accept our privacy policy'); $form->add($privacy); $button = new Button('submit'); $button->setAttribute('value', 'Send'); $form->add($button); if($form->isValid()){ print_r($form->getValues()); // do what you want } // render the form echo $form->render(); This piece of code creates a simple contact form and validates it according to the validation rules set. Inside the isValid() method you can run your code (fe sending an email) Highlights: 30+ validation types Support for UiKit 3 and Bootstrap 5 CSS framework SPAM protection Highly customizable Hookable methods for further customization Multi-language You can download and find really extensive information on how to use at https://github.com/juergenweb/FrontendForms. Please report errors or suggestions directly in GitHub. Best regards and happy testing ? If you have downloaded the module in the past I recommend you to uninstall the module completely and install the newest version 2.1.14. There are a lot of changes in the new version, so please test carefully.
- 407 replies
-
- 26
-
-
-
Hello community! I want to share a new module I've been working on that I think could be a big boost for multi-language ProcessWire sites. Fluency is available in the ProcessWire Modules Directory, via Composer, and on Github Some background: I was looking for a way for our company website to be efficiently translated as working with human translators was pretty laborious and a lack of updating content created a divergence between languages. I, and several other devs here, have talked about translation integrations and the high quality services now available. Inspired by what is possible with ProcessWire, I built Fluency, a third-party translation service integration for ProcessWire. With Fluency you can: Translate any plain textarea or text input Translate any TinyMCE or CKEditor (inline, or regular) Translate page names/URLs Translate in-template translation function wrapped strings Translate modules, both core and add-ons Installation and usage is completely plug and play. Whether you're building a new multi-language site, need to update a site to multi-language, or simply want to stop manually translating a site and make any language a one-click deal, it could not be easier to do it. Fluency works by having you match the languages configured in ProcessWire to those offered by the third party translation service you choose. Currently Fluency works with DeepL and Google Cloud Translation. Module Features Translate any multilanguage field while editing any page. Translate fields in Repeater, Repeater Matrix, Table, Fieldset Page, Image descriptions, etc. Translate any file that added in the ProcessWire language pages. It's possible to translate the entire ProcessWire core in ~20 minutes Provide intuitive translation features that your clients and end-users can actually use. Fluency is designed for real-world use by individuals of all skill levels with little to no training. Its ease-of-use helps encourage users to adopt a multilanguage workflow. Start for free, use for free. Translation services supported by Fluency offer generous free tiers that can support regular usage levels. Fluency is, and will always be, free and open source. Use more than one Translation Engine. You may configure Fluency to use either DeepL, Google Cloud Translation, or both by switching between them as desired. AI powered translations that rival humans. DeepL provides the highest levels of accuracy in translation of any service available. Fluency has been used in many production sites around the world and in commercial applications where accuracy matters. Deliver impressive battle-tested translation features your clients can count on. Disable translation for individual fields. Disable translation for multilanguage fields where values aren't candidates for translation such as phone numbers or email addresses Configure translation caching. Caching can be enabled globally so that the same content translated more than once anywhere in ProcessWire doesn't count against your API usage and provides lightning fast responses. Set globally ignored words and text. Configure Fluency to add exclusionary indicators during translation so that specific words or phrases remain untranslated. This works either for specific strings alone, or present in other content while remaining grammatically correct in translation. Choose how translation is handled for fields. Configure Fluency to have buttons for either "Translate from {default language}" on each tab, or "Translate To All Languages" to populate every language for a field from any language to any language you have configured. No language limits. Configure as few or as many languages as you need. 2, 5, 10, 20 language website? Absolutely possible. If the translation service you choose offers a language, you can use it in ProcessWire. When new languages are introduced by third parties, they're ready to use in Fluency. Visually see what fields and language tabs have modified content. Fluency adds an visual indication to each field language tab to indicate which has different content than when opening the edit page. This helps ensure that content updated in one language should be updated in other languages to prevent content divergence between languages. Render language meta tags and ISO codes. Output alt language meta tags, add the current language's ISO code to your <html lang=""> attribute to your templates that are automatically generated from accurate data from the third party translation service. Build a standards-compliant multi-language SEO ready page in seconds with no additional configuration. Render language select elements. - Fluency can generate an unordered list of language links to switch between languages when viewing your pages. You can also embed a <select> element with JS baked in to switch between languages when viewing your pages. Render it without JS to use your own. Manage feature access for users. Fluency provides a permission that can be assigned to user roles for managing who can translate content. Track your translation account usage. View your current API usage, API account limit, and remaining allotment to keep an eye on and manage usage. (Currently only offered by DeepL) Use the global translation tool. Fluency provides translation on each field according to the languages you configure in ProcessWire. Use the global translation tool to translate any content to any language. Use Fluency from your templates and code. All translation features, usage statistics, cache control, and language data are accessible globally from the $fluency object. Perform any operation and get data for any language programmatically wherever you need it. Build custom AJAX powered admin translation features for yourself. Fluency provides a full RESTful API within the ProcessWire admin to allow developers to add new features for ProcessWire applications powered by the same API that Fluency uses. Robust plain-language documentation that helps you get up to speed fast. Fluency is extremely easy to use but also includes extensive documentation for all features both within the admin and for the Fluency programming API via the README.md document. The module code itself is also fully annotated for use with the ProDevTools API explorer. Is and will always be data safe. Adding, upgrading, or removing Fluency does not modify or remove your content. ProcessWire handles your data, Fluency sticks to translating. Full module localization. Translate Fluency itself to any language. All buttons, messages, and UI elements for Fluency will be presented in any language you choose for the ProcessWire admin. Built for expansion. Fluency provides translation services as modular "Translation Engines" with a full framework codebase to make adding new translation services easier and more reliable. Contributions for new translation services are welcome. Fluency is designed and built to provide everything you need to handle incredibly accurate translations and robust tools that make creating and managing multi-language sites a breeze. Built through research on translation plugins from around the web, it's the easiest and most friendly translation implementation for both end users and developers on any CMS/CMF anywhere. Fluency complements the built-in first class language features of ProcessWire. Fluency continues to be improved with great suggestions from the community and real-world use in production applications. Big thanks to everyone who has helped make Fluency better. Contributions, suggestions, and bug reports welcome! Please note that the browser plugin for Grammarly conflicts with Fluency (as it does with many web applications). To address this issue it is recommended that you disable Grammarly when using Fluency, or open the admin to edit pages in a private window where Grammarly may not be loaded. This is a long-standing issue in the larger web development community and creating a workaround may not be possible. If you have insight as to how this may be solved please visit the Github page and file a bugfix ticket. Enhancements Translate All Fields On A Page Compatibility with newest rewrite of module is in progress... An exciting companion module has been written by @robert which extends the functionality of Fluency to translate all fields on a page at once. The module has several useful features that can make Fluency even more useful and can come in handy for translating existing content more quickly. I recommend reading his comments for details on how it works and input on best practices later in this thread. Get the module at the Github repo: https://github.com/robertweiss/ProcessTranslatePage Requirements: ProcessWire 3.0+ UIKit Admin Theme That's Fluency in a nutshell. The Module Is Free This is my first real module and I want to give it back to the community as thanks. This is the best CMS I've worked with (thank you Ryan & contributors) and a great community (thank you dear reader). DeepL Developer Accounts In addition to paid Pro Developer accounts, DeepL now offers no-cost free accounts. All ProcessWire developers and users can use Fluency at no cost. Learn more about free and paid accounts by visiting the DeepL website. Sign up for a Developer account, get an API key, and start using Fluency. Download You can install Fluency by adding the module to your ProcessWire project using any of the following methods. Method 1: Within ProcessWire using 'Add Module From Directory' and the class name Fluency Method 2: Via Composer with composer require firewire/fluency Method 3: Download from the Github repository and unzip the contents into /site/modules/ Feedback File issues and feature requests here (your feedback and testing is greatly appreciated): https://github.com/SkyLundy/Fluency/issues Thank you! ¡Gracias! Ich danke Ihnen! Merci! Obrigado! Grazie! Dank u wel! Dziękuję! Спасибо! ありがとうございます! 谢谢你
- 294 replies
-
- 43
-
-
-
- translation
- language
-
(and 1 more)
Tagged with:
-
Hey folks! Took a couple of late nights, but managed to turn this old gist of mine into a proper module. The name is SearchEngine, and currently it provides support for indexing page contents (into a hidden textarea field created automatically), and also includes a helper feature ("Finder") for querying said contents. No fancy features like stemming here yet, but something along those lines might be added later if it seems useful (and if I find a decent implementation to integrate). Though the API and selector engine make it really easy to create site search pages, I pretty much always end up duplicating the same features from site to site. Also – since it takes a bit of extra time – it's tempting to skip over some accessibility related things, and leave features like text highlighting out. Overall I think it makes sense to bundle all that into a module, which can then be reused over and over again ? Note: markup generation is not yet built into the module, which is why the examples below use PageArray::render() method to produce a simple list of results. This will be added later on, as a part of the same module or a separate Markup module. There's also no fancy JS API or anything like that (yet). This is an early release, so be kind – I got the find feature working last night (or perhaps this morning), and some final tweaks and updates were made just an hour ago ? GitHub repository: https://github.com/teppokoivula/SearchEngine Modules directory: https://modules.processwire.com/modules/search-engine/ Demo: https://wireframe-framework.com/search/ Usage Install SearchEngine module. Note: the module will automatically create an index field install time, so be sure to define a custom field (via site config) before installation if you don't want it to be called "search_index". You can change the field name later as well, but you'll have to update the "index_field" option in site config or module settings (in Admin) after renaming it. Add the site search index field to templates you want to make searchable. Use selectors to query values in site search index. Note: you can use any operator for your selectors, you will likely find the '=' and '%=' operators most useful here. You can read more about selector operators from ProcessWire's documentation. Options By default the module will create a search index field called 'search_index' and store values from Page fields title, headline, summary, and body to said index field when a page is saved. You can modify this behaviour (field name and/or indexed page fields) either via the Module config screen in the PocessWire Admin, or by defining $config->SearchEngine array in your site config file or other applicable location: $config->SearchEngine = [ 'index_field' => 'search_index', 'indexed_fields' => [ 'title', 'headline', 'summary', 'body', ], 'prefixes' => [ 'link' => 'link:', ], 'find_args' => [ 'limit' => 25, 'sort' => 'sort', 'operator' => '%=', 'query_param' => null, 'selector_extra' => '', ], ]; You can access the search index field just like any other ProcessWire field with selectors: if ($q = $sanitizer->selectorValue($input->get->q)) { $results = $pages->find('search_index%=' . $query_string . ', limit=25'); echo $results->render(); echo $results->renderPager(); } Alternatively you can delegate the find operation to the SearchEngine module: $query = $modules->get('SearchEngine')->find($input->get->q); echo $query->resultsString; // alias for $query->results->render() echo $query->pager; // alias for $query->results->renderPager() Requirements ProcessWire >= 3.0.112 PHP >= 7.1.0 Note: later versions of the module may require Composer, or alternatively some additional features may require installing via Composer. This is still under consideration – so far there's nothing here that would really depend on it, but advanced features like stemming most likely would. Installing It's the usual thing: download or clone the SearchEngine directory into your /site/modules/ directory and install via Admin. Alternatively you can install SearchEngine with Composer by executing composer require teppokoivula/search-engine in your site directory.
- 300 replies
-
- 33
-
-
-
Hi @Morphosis - glad you found a solution! Based on the module documentation on Github, you can also define this in your site/config.php using an array-based syntax. Choose whichever method you would prefer! Example: /** * Module: SearchEngine * * Override any module settings or other config values here. Anything set here * cannot be overridden. * */ $config->SearchEngine = [ // Render arguments affect the rendered output from the SearchEngine module. 'render_args' => [ // Various attributes used by the search form and results list when rendered. 'form_action' => '/search/', ] ];
-
Textformatter module Textblocks renders content double
Jan S. replied to Jan S.'s topic in General Support
Hello all, @BFD Calendar - this did actually the trick. If no user is logged in the textblocks render once as expected. Thanks for the hint! I also figured out, that this behaviour depends on frontend editing, which is enabled for this particular field in my case. Once this is disabled, it also works fine even when logged on to processwire's backend. For my scenario I m fine, however, I think it is a small glitch and could be enhanced... any opinions if I should file a bug report for this and how and where? Many thanks! -
@Stefanowitsch asked about using the File Mover module with a "media library" page that is accessed via a modal. I thought I would share some hook code publicly in case it's useful for others too. // Add a button to file and image fields to open a media library page in a modal // Hook InputfieldFile::render to affect file and image fields, // or InputfieldImage::render to affect only image fields $wire->addHookAfter('InputfieldFile::render', function(HookEvent $event) { $inputfield = $event->object; // The field associated with the inputfield (if any) $field = $inputfield->hasField; // The page containing the inputfield (if any) $page = $inputfield->hasPage; // Don't add the button to fields on the media library page // as we don't want the possibility of nested modals if($page && $page->template == 'media_library') return; // You can also check the field name if the button should only be added to a specific field, e.g. // if($field && $field->name !== 'article_images') return; // Get the media library page $media_library = $event->wire()->pages->get("template=media_library"); // Construct the URL to edit the media library page $url = $media_library->editUrl; // Add &modal=1 so the admin header isn't shown $url .= '&modal=1'; // We don't need other tabs or fields besides the image/file field(s), // so specify the field name(s) in the URL // Unfortunately there is this layout bug: https://github.com/processwire/processwire-issues/issues/1972 $url .= '&field=images,files'; /** @var InputfieldButton $f */ $f = $event->wire()->modules->get('InputfieldButton'); $f->href = $url; $f->value = 'Open media library'; $f->icon = 'picture-o'; // Add pw-modal class so the button link opens in a modal $f->addClass('pw-modal'); // Make it a large modal $f->addClass('pw-modal-large'); // Add a bit of space above the button $f->attr('style', 'margin-top: 10px;'); // Append the rendered button to the inputfield $event->return .= $f->render(); });
-
Textformatter module Textblocks renders content double
BrendonKoz replied to Jan S.'s topic in General Support
Hi @Jan S.! Welcome to the forum, and congratulations on your first post! We're glad to have you. 😊 Based on what you're showing, your code looks good from what I can see of the TextBlocks documentation, so I am not entirely sure what to suggest, other than maybe seeing if removing the "echo" from your template call to the field will still render the field. I don't think it should, but since it's being duplicated, it can't hurt to try. Beyond that, TextBlocks is a paid ProDevTools module, so support for that module is in its own forum, locked down for paid/active module owners. Assuming your module support status is up-to-date, that can be found in the ProFields Support subforum here. -
I just reinstall Processwire with latest RockPageBuilder (6.5.2). After adding a Content-Element (Afred oder Backend) I get an error: Error: Call to a member function render() on string search► RockDevTools LiveReload is active File: .../modules/RockPageBuilder/RockPageBuilder.module.php:1596 1586: } 1587: 1588: /** 1589: * Render content of blocks field 1590: */ 1591: public function render($renderPlus = true) 1592: { 1593: $page = $this->wire->page; 1594: $field = $page->getFormatted(self::field_blocks); 1595: if (!$field) return; 1596: $html = $field->render($renderPlus); 1597: $rf = $this->wire->rockfrontend; 1598: if ($rf) return $rf->html($html); 1599: return $html; 1600: } In Latte-Template: {if $modules->isInstalled('RockPageBuilder')} <main sortable> {$rockpagebuilder->render(true)} </main> {else} If I delete the Content-Element it works like expected.
-
I think experimenting with a block-style editor would be great. In the very large discussion over WYSIWYG editors (I don't recall of this was a 2025 wishlist, or a discussion of the future of TinyMCE/CKEditor, but it had a LOT of paginated responses), a few people even experimented in creating a proof-of-concept with editor.js, showing their results. I gave it a shot but determined the end result (interface) was too cumbersome for most of my users (and I usually try to aim for a very low bar as a standard; less complaints / support needed). Even in the demo (tried today) I was able to cause a rendering bug in both of the editors mentioned (TipTap, Editor.js) above. That said, if a true module is attempted to be released, since they render and use JSON as the underlying structure, I would recommend using a similar database structure to TinyMCE and/or CKEditor, and save the HTML-rendered output in a field just in case someone wished to switch back to a standard text editor for a particular field. (Unfortunately that means only one-way compatibility, however - and increased storage costs/size...so maybe an option for that in the module.)
-
Example: foreach($list_of_cards as $card){ // cache cleared then selector matches $files->render("inc/some-include", $vars , ["cache" => "template=some_template", "name" => "template_cache_{$card->id}"]) } Available since version 3.0.130
-
I have added a hook recorder and this is what I got when logging in with a non-existing email address: ProcessWire\ProcessLogin::execute ProcessWire\ProcessLogin::buildLoginForm ProcessWire\ProcessLogin::loginFormProcessReady ProcessWire\ProcessLogin::loginFailed ProcessWire\ProcessLogin::loginFormProcessed ProcessWire\ProcessLogin::renderLoginForm ProcessWire\ProcessLogin::headline ProcessWire\ProcessLogin::getLoginLinks ProcessWire\ProcessLogin::executed So to me it looks like loginFormProcessReady should work. This is the whole hook recorder log, which looks like InputfieldForm::processInput should also be an option? ProcessWire\Fields::load ProcessWire\Fieldgroups::load ProcessWire\Templates::load ProcessWire\Fieldgroup::setQuietly ProcessWire\Fieldgroup::callUnknown ProcessWire\Fieldgroup::setQuietly ProcessWire\Fieldgroup::callUnknown ProcessWire\Fieldgroup::setQuietly ProcessWire\Fieldgroup::callUnknown ProcessWire\Fieldgroup::setQuietly ProcessWire\Fieldgroup::callUnknown ProcessWire\Fieldgroup::setQuietly ProcessWire\Fieldgroup::callUnknown ProcessWire\Session::init ProcessWire\ProcessWire::init ProcessWire\Pages::find ProcessWire\Pages::find ProcessWire\PageFinder::find ProcessWire\PageFinder::getQuery ProcessWire\FieldgroupsArray::changed ProcessWire\FieldsArray::changed ProcessWire\FieldsArray::changed ProcessWire\FieldgroupsArray::changed ProcessWire\Fieldgroup::setQuietly ProcessWire\Fieldgroup::callUnknown ProcessWire\TemplatesArray::changed ProcessWire\TemplatesArray::changed ProcessWire\FieldgroupsArray::changed ProcessWire\FieldsArray::changed ProcessWire\FieldsArray::changed ProcessWire\FieldgroupsArray::changed ProcessWire\Fieldgroup::setQuietly ProcessWire\Fieldgroup::callUnknown ProcessWire\TemplatesArray::changed ProcessWire\TemplatesArray::changed ProcessWire\FieldgroupsArray::changed ProcessWire\FieldgroupsArray::changed ProcessWire\Fieldgroup::setQuietly ProcessWire\Fieldgroup::callUnknown ProcessWire\TemplatesArray::changed ProcessWire\TemplatesArray::changed ProcessWire\FieldgroupsArray::changed ProcessWire\FieldsArray::changed ProcessWire\FieldsArray::changed ProcessWire\FieldsArray::changed ProcessWire\FieldsArray::changed ProcessWire\FieldsArray::changed ProcessWire\FieldsArray::changed ProcessWire\FieldsArray::changed ProcessWire\FieldsArray::changed ProcessWire\FieldsArray::changed ProcessWire\FieldsArray::changed ProcessWire\FieldgroupsArray::changed ProcessWire\Fieldgroup::setQuietly ProcessWire\Fieldgroup::callUnknown ProcessWire\TemplatesArray::changed ProcessWire\TemplatesArray::changed ProcessWire\Pages::find ProcessWire\PageFinder::find ProcessWire\PageFinder::getQuery ProcessWire\Pages::find ProcessWire\PageFinder::find ProcessWire\PageFinder::getQuery ProcessWire\Pages::find ProcessWire\PageFinder::find ProcessWire\PageFinder::getQuery ProcessWire\FieldgroupsArray::changed ProcessWire\FieldgroupsArray::changed ProcessWire\Fieldgroup::setQuietly ProcessWire\Fieldgroup::callUnknown ProcessWire\TemplatesArray::changed ProcessWire\TemplatesArray::changed ProcessWire\Pages::find ProcessWire\PageFinder::find ProcessWire\PageFinder::getQuery ProcessWire\UserPage::hasPagePermission ProcessWire\Pages::find ProcessWire\PageFinder::find ProcessWire\PageFinder::getQuery ProcessWire\ProcessPageView::execute ProcessWire\PagesRequest::getPage ProcessWire\PagesRequest::getPageForUser ProcessWire\DefaultPage::viewable ProcessWire\PagesRequest::getLoginPageOrUrl ProcessWire\Pages::find ProcessWire\ProcessPageView::ready ProcessWire\ProcessWire::ready ProcessWire\Config::InputfieldWrapper ProcessWire\Config::callUnknown ProcessWire\JqueryUI::use ProcessWire\PageFrontEdit::getPage ProcessWire\FieldgroupsArray::changed ProcessWire\Fieldgroup::setQuietly ProcessWire\Fieldgroup::callUnknown ProcessWire\FieldgroupsArray::changed ProcessWire\Fieldgroup::setQuietly ProcessWire\Fieldgroup::callUnknown ProcessWire\FieldgroupsArray::changed ProcessWire\Fieldgroup::setQuietly ProcessWire\Fieldgroup::callUnknown ProcessWire\FieldgroupsArray::changed ProcessWire\Fieldgroup::setQuietly ProcessWire\Fieldgroup::callUnknown ProcessWire\TemplatesArray::changed ProcessWire\TemplatesArray::changed ProcessWire\TemplatesArray::changed ProcessWire\TemplatesArray::changed ProcessWire\TemplatesArray::changed ProcessWire\Pages::find ProcessWire\PageFinder::find ProcessWire\PageFinder::getQuery ProcessWire\Pages::find ProcessWire\PageFinder::find ProcessWire\PageFinder::getQuery ProcessWire\Pages::find ProcessWire\PageFinder::find ProcessWire\PageFinder::getQuery ProcessWire\Pages::find ProcessWire\Pages::find ProcessWire\Pages::find ProcessWire\Pages::find ProcessWire\PageFinder::find ProcessWire\PageFinder::getQuery ProcessWire\Pages::find ProcessWire\PageFinder::find ProcessWire\PageFinder::getQuery ProcessWire\TemplateFile::render ProcessWire\DefaultPage::render ProcessWire\PageRender::renderPage ProcessWire\TemplateFile::render ProcessWire\ProcessController::execute ProcessWire\UserPage::hasPagePermission ProcessWire\Pages::find ProcessWire\UserPage::hasPagePermission ProcessWire\Pages::find ProcessWire\ProcessLogin::execute ProcessWire\ProcessLogin::buildLoginForm ProcessWire\ProcessLogin::loginFormProcessReady ProcessWire\InputfieldForm::processInput ProcessWire\InputfieldText::processInput ProcessWire\InputfieldText::processInput ProcessWire\InputfieldSubmit::processInput ProcessWire\InputfieldHidden::processInput ProcessWire\InputfieldHidden::processInput ProcessWire\InputfieldHidden::processInput ProcessWire\InputfieldHidden::processInput ProcessWire\Pages::find ProcessWire\PageFinder::find ProcessWire\PageFinder::getQuery ProcessWire\ProcessLogin::loginFailed ProcessWire\ProcessLogin::loginFormProcessed ProcessWire\ProcessLogin::renderLoginForm ProcessWire\ProcessLogin::headline ProcessWire\InputfieldForm::render ProcessWire\InputfieldForm::renderInputfield ProcessWire\InputfieldText::render ProcessWire\InputfieldForm::renderInputfield ProcessWire\InputfieldText::render ProcessWire\InputfieldForm::renderInputfield ProcessWire\InputfieldSubmit::render ProcessWire\InputfieldForm::renderInputfield ProcessWire\InputfieldHidden::render ProcessWire\InputfieldForm::renderInputfield ProcessWire\InputfieldHidden::render ProcessWire\InputfieldForm::renderInputfield ProcessWire\InputfieldHidden::render ProcessWire\InputfieldForm::renderInputfield ProcessWire\InputfieldHidden::render ProcessWire\ProcessLogin::getLoginLinks ProcessWire\Pages::find ProcessWire\ProcessLogin::executed ProcessWire\AdminThemeUikit::getExtraMarkup ProcessWire\AdminThemeUikit::getExtraMarkup ProcessWire\AdminThemeUikit::getUikitCSS ProcessWire\AdminThemeUikit::getExtraMarkup ProcessWire\AdminThemeUikit::getExtraMarkup ProcessWire\AdminThemeUikit::getExtraMarkup ProcessWire\AdminThemeUikit::renderBreadcrumbs ProcessWire\AdminThemeUikit::getExtraMarkup ProcessWire\AdminThemeUikit::getExtraMarkup ProcessWire\Pages::find ProcessWire\PageFinder::find ProcessWire\PageFinder::getQuery ProcessWire\Pages::find ProcessWire\Pages::find ProcessWire\PageFinder::find ProcessWire\PageFinder::getQuery ProcessWire\ProcessPageView::finished ProcessWire\ProcessWire::finished ProcessWire\DefaultPage::viewable ProcessWire\DefaultPage::rootParent ProcessWire\DefaultPage::viewable ProcessWire\DefaultPage::rootParent ProcessWire\DefaultPage::rootParent ProcessWire\DefaultPage::rootParent ProcessWire\PageFinder::find ProcessWire\PageFinder::getQuery ProcessWire\DefaultPage::viewable ProcessWire\PageFinder::find ProcessWire\PageFinder::getQuery ProcessWire\DefaultPage::viewable ProcessWire\FieldsArray::changed ProcessWire\FieldsArray::changed ProcessWire\FieldsArray::changed ProcessWire\DefaultPage::viewable ProcessWire\DefaultPage::editable ProcessWire\UserPage::hasPagePermission ProcessWire\Pages::find ProcessWire\PageFinder::find ProcessWire\PageFinder::getQuery ProcessWire\DefaultPage::addable ProcessWire\UserPage::hasPagePermission ProcessWire\Pages::find ProcessWire\DefaultPage::publishable ProcessWire\DefaultPage::editable ProcessWire\UserPage::hasPagePermission ProcessWire\Pages::find ProcessWire\DefaultPage::listable ProcessWire\DefaultPage::moveable ProcessWire\DefaultPage::editable ProcessWire\UserPage::hasPagePermission ProcessWire\Pages::find ProcessWire\DefaultPage::sortable ProcessWire\DefaultPage::editable ProcessWire\UserPage::hasPagePermission ProcessWire\Pages::find ProcessWire\DefaultPage::deleteable ProcessWire\DefaultPage::trashable ProcessWire\DefaultPage::restorable ProcessWire\DefaultPage::rootParent ProcessWire\Pages::find ProcessWire\PageFinder::find ProcessWire\PageFinder::getQuery ProcessWire\PageArray::changed ProcessWire\DefaultPage::viewable ProcessWire\User::hasPagePermission ProcessWire\Pages::find ProcessWire\DefaultPage::editable ProcessWire\User::hasPagePermission ProcessWire\Pages::find ProcessWire\DefaultPage::addable ProcessWire\User::hasPagePermission ProcessWire\Pages::find ProcessWire\DefaultPage::publishable ProcessWire\DefaultPage::editable ProcessWire\User::hasPagePermission ProcessWire\Pages::find ProcessWire\DefaultPage::listable ProcessWire\User::hasPagePermission ProcessWire\Pages::find ProcessWire\User::hasPagePermission ProcessWire\Pages::find ProcessWire\DefaultPage::moveable ProcessWire\DefaultPage::editable ProcessWire\User::hasPagePermission ProcessWire\Pages::find ProcessWire\DefaultPage::sortable ProcessWire\DefaultPage::editable ProcessWire\User::hasPagePermission ProcessWire\Pages::find ProcessWire\DefaultPage::deleteable ProcessWire\DefaultPage::trashable ProcessWire\DefaultPage::restorable ProcessWire\DefaultPage::rootParent ProcessWire\PageArray::changed ProcessWire\PageArray::changed ProcessWire\DefaultPage::viewable ProcessWire\DefaultPage::editable ProcessWire\DefaultPage::addable ProcessWire\DefaultPage::publishable ProcessWire\DefaultPage::listable ProcessWire\DefaultPage::moveable ProcessWire\DefaultPage::editable ProcessWire\User::hasPagePermission ProcessWire\Pages::find ProcessWire\PageFinder::find ProcessWire\PageFinder::getQuery ProcessWire\DefaultPage::sortable ProcessWire\DefaultPage::editable ProcessWire\User::hasPagePermission ProcessWire\DefaultPage::deleteable ProcessWire\DefaultPage::trashable ProcessWire\DefaultPage::restorable ProcessWire\DefaultPage::rootParent ProcessWire\WireCache::log ProcessWire\WireCache::log ProcessWire\WireDateTime::relativeTimeStr ProcessWire\WireDateTime::relativeTimeStr ProcessWire\WireDateTime::relativeTimeStr ProcessWire\WireDateTime::relativeTimeStr ProcessWire\Session::changed ProcessWire\Session::changed ProcessWire\WireCache::log ProcessWire\WireCache::log ProcessWire\Fields::load ProcessWire\Fieldgroups::load ProcessWire\Templates::load ProcessWire\Fieldgroup::setQuietly ProcessWire\Fieldgroup::callUnknown ProcessWire\Fieldgroup::setQuietly ProcessWire\Fieldgroup::callUnknown ProcessWire\Fieldgroup::setQuietly ProcessWire\Fieldgroup::callUnknown ProcessWire\Fieldgroup::setQuietly ProcessWire\Fieldgroup::callUnknown ProcessWire\Fieldgroup::setQuietly ProcessWire\Fieldgroup::callUnknown ProcessWire\Session::init
-
I've been meaning to revise PageimageSrcset for a while now, to remove some features that I felt were unnecessary and to implement a better rendering strategy. The result is PageimageSource. What does it do? It provides a configurable srcset method/property for Pageimage It allows WebP to be enabled for images it generates. It allows Pageimage:render() to return a <picture> element It provides a Textformatter that replaces <img> elements with the output of Pageimage:render() Although it is based on a current module, this should still be considered beta and not used in production without a prior development stage. Here's the README: PageimageSource Extends Pageimage with a srcset property/method plus additional rendering options. Overview The main purpose of this module is to make srcset implementation as simple as possible in your template code. For an introduction to srcset, please read this Mozilla article about responsive images. Installation Download the zip file at Github or clone the repo into your site/modules directory. If you downloaded the zip file, extract it in your sites/modules directory. In your admin, go to Modules > Refresh, then Modules > New, then click on the Install button for this module. ProcessWire >= 3.0.165 and PHP >= 7.3 are required to use this module. Configuration To configure this module, go to Modules > Configure > PageimageSource. Default Set Rules These are the default set rules that will be used when none are specified, e.g. when calling the property: $image->srcset. Each set rule should be entered on a new line, in the format {width}x{height} {inherentwidth}w|{resolution}x. Not all arguments are required - you will probably find that specifying the width is sufficient for most cases. Here's a few examples of valid set rules and the sets they generate: Set Rule Set Generated Arguments Used 320 image.320x0-srcset.jpg 320w {width} 480x540 image.480x540-srcset.jpg 480w {width}x{height} 640x480 768w image.640x480-srcset.jpg 768w {width}x{height} {inherentwidth}w 2048 2x image.2048x0-srcset.jpg 2x {width} {resolution}x How you configure your rules is dependent on the needs of the site you are developing; there are no prescriptive rules that will meet the needs of most situations. This article gives a good overview of some of the things to consider. When you save your rules, a preview of the sets generated and an equivalent method call will be displayed to the right. Invalid rules will not be used, and you will be notified of this. WebP If enabled, WebP versions of the image and srcset variations will be generated and these will be returned by Pageimage::srcset(). As with the default implementation, the image with the smaller file size is returned. In most cases this is the WebP version, but sometimes can be the source. Make sure to experiment with the quality setting to find a value you find suitable. The default value of 90 is fine, but it is possible that lower values will give you excellent kB savings with little change in overall quality. For more information on WebP implementation please read the blog posts on the ProcessWire website. Rendering These settings control how the output of Pageimage::render() is modified. Use Lazy Loading? When enabled this adds loading="lazy" to the <img> attributes. It is useful to have this on by default, and you can always override it in the options for a specific image. Use the <picture> element? When enabled, the <img> element is wrapped in a <picture> element and <source> elements for original and WebP variations are provided. This requires WebP to be enabled. For more information on what this does, have a look at the examples in Pageimage::render() below. Remove Variations If checked, the image variations generated by this module are cleared on Submit. On large sites, this may take a while. It makes sense to run this after you have made changes to the set rules. Please note that although the module will generate WebP versions of all images if enabled, it will only remove the variations with the 'srcset' suffix. Usage Pageimage::srcset() // The property, which uses the set rules in the module configuration $srcset = $image->srcset; // A method call, using a set rules string // Delimiting with a newline (\n) would also work, but not as readable $srcset = $image->srcset('320, 480, 640x480 768w, 1240, 2048 2x'); // The same as above but using an indexed/sequential array $srcset = $image->srcset([ '320', '480', '640x480 768w', '1240', '2048 2x', ]); // The same as above but using an associative array // No rule checking is performed $srcset = $image->srcset([ '320w' => [320], '480w' => [480], '768w' => [640, 480], '1240w' => [1240], '2x' => [2048], ]); // The set rules above are a demonstration, not a recommendation! Image variations are only created for set rules which require a smaller image than the Pageimage itself. This may still result in a lot of images being generated. If you have limited storage, please use this module wisely. Pageimage::render() This module extends the options available to this method with: srcset: When the module is installed, this will always be added, unless set to false. Any values in the formats described above can be passed. sizes: If no sizes are specified, a default of 100vw is assumed. lazy: Pass true to add loading=lazy, otherwise false to disable if enabled in the module configuration. picture: Pass true to use the <picture> element, otherwise false to disable if enabled in the module configuration. Please refer to the API Reference for more information about this method. // Render an image using the default set rules // WebP and lazy loading are enabled, and example output is given for <picture> disabled and enabled echo $image->render(); // <img src='image.webp' alt='' srcset='image.jpg...' sizes='100vw' loading='lazy'> /* <picture> <source srcset="image.webp..." sizes="100vw" type="image/webp"> <source srcset="image.jpg..." sizes="100vw" type="image/jpeg"> <img src="image.jpg" alt="" loading="lazy"> </picture> */ // Render an image using custom set rules echo $image->render(['srcset' => '480, 1240x640']); // <img src='image.webp' alt='' srcset='image.480x0-srcset.webp 480w, image.1240x640-srcset.webp 1240w' sizes='100vw' loading='lazy'> /* <picture> <source srcset="image.480x0-srcset.webp 480w, image.1240x640-srcset.webp 1240w" sizes="100vw" type="image/webp"> <source srcset="image.480x0-srcset.jpg 480w, image.1240x640-srcset.jpg 1240w" sizes="100vw" type="image/jpeg"> <img src="image.jpg" alt="" loading="lazy"> </picture> */ // Render an image using custom set rules and sizes // Also use the `markup` argument // Also disable lazy loading // In this example the original jpg is smaller than the webp version echo $image->render('<img class="image" src="{url}" alt="Image">', [ 'srcset' => '480, 1240', 'sizes' => '(min-width: 1240px) 50vw', 'lazy' => false, ]); // <img class='image' src='image.jpg' alt='Image' srcset='image.480x0-srcset.webp 480w, image.1240x0-srcset.webp 1240w' sizes='(min-width: 1240px) 50vw'> /* <picture> <source srcset="image.480x0-srcset.webp 480w, image.1240x0-srcset.webp 1240w" sizes="(min-width: 1240px) 50vw" type="image/webp"> <source srcset="image.480x0-srcset.jpg 480w, image.1240x0-srcset.jpg 1240w" sizes="(min-width: 1240px) 50vw" type="image/jpeg"> <img class='image' src='image.jpg' alt='Image'> </picture> */ // Render an image using custom set rules and sizes // These rules will render 'portrait' versions of the image for tablet and mobile // Note the advanced use of the `srcset` option passing both `rules` and image `options` // WebP is disabled // Picture is disabled echo $image->render([ 'srcset' => [ 'rules' => '320x569, 640x1138, 768x1365, 1024, 1366, 1600, 1920', 'options' => [ 'upscaling' => true, 'hidpi' => true, ], ], 'sizes' => '(orientation: portrait) and (max-width: 640px) 50vw', 'picture' => false, ]); // <img src='image.jpg' alt='' srcset='image.320x569-srcset-hidpi.jpg 320w, image.640x1138-srcset-hidpi.jpg 640w, image.768x1365-srcset-hidpi.jpg 768w, image.1024x0-srcset-hidpi.jpg 1024w, image.1366x0-srcset-hidpi.jpg 1366w, image.1600x0-srcset-hidpi.jpg 1600w, image.jpg 1920w' sizes='(orientation: portrait) and (max-width: 768px) 50vw' loading="lazy"> TextformatterPageimageSource Bundled with this module is a Textformatter largely based on TextformatterWebpImages by Ryan Cramer. When applied to a field, it searches for <img> elements and replaces them with the default output of Pageimage::render() for each image/image variation. Assuming a default set of 480, 960 and lazy loading enabled, here are some examples of what would be returned: Example <figure class="align_right hidpi"> <a href="/site/assets/files/1/example.jpg"> <img alt="" src="/site/assets/files/1/example.300x0-is-hidpi.jpg" width="300" /> </a> </figure> WebP enabled <figure class="align_right hidpi"> <a href="/site/assets/files/1/example.jpg"> <img alt="" src="/site/assets/files/1/example.300x0-is-hidpi.webp" width="300" srcset="/site/assets/files/1/example.300x0-is-hidpi.webp 480w" sizes="100vw" loading="lazy" /> </a> </figure> <picture> enabled <figure class="align_right hidpi"> <a href="/site/assets/files/1/example.jpg"> <picture> <source srcset="/site/assets/files/1/example.300x0-is-hidpi.webp 480w" sizes="100vw" type="image/webp"> <source srcset="/site/assets/files/1/example.300x0-is-hidpi.jpg 480w" sizes="100vw" type="image/jpeg"> <img alt="" src="/site/assets/files/1/example.300x0-is-hidpi.jpg" width="300" loading="lazy" /> </picture> </a> </figure> Because the variation is small - 300px wide - the srcset only returns the source image variation at the lowest set width (480w). If the source image was > 1000px wide, there would be a variation at both 480w and 960w. PageimageSrcset This module is built upon work done for PageimageSrcset, which can be considered a first iteration of this module, and is now deprecated. Migration PageimageSource is a simplified version of PageimageSrcset with a different approach to rendering. Most of the features of the old module have been removed. If you were just using $image->srcset(), migration should be possible, as this functionality is essentially the same albeit with some improvements to image variation generation.
- 86 replies
-
- 22
-
-
-
enum TournamentType:string { case MYSTERY = "Mystery"; case PKO = "PKO"; case VANILLA = "Vanilla"; } class FilterSolvesForm extends AbstractFrontendForm { protected function buildForm(): void { $tournamentTypeSelect = new Select("tournamentType"); $tournamentTypeSelect->setLabel(__("Type de tournoi")); foreach (TournamentType::cases() as $tournamentType) { $tournamentTypeSelect->addOption($tournamentType->value, $tournamentType->value); } $this->add($tournamentTypeSelect); } } abstract class AbstractFrontendForm extends Form { public function __construct(string $id) { parent::__construct($id); $this->buildForm(); $this->addSubmit(); } private function addSubmit():void { $button = new Button('submit'); $button->setAttribute('value', __("Valider")); $this->add($button); } abstract protected function buildForm(): void; } // TEMPLATE PHP FILE $command = new SelectSolvesDatabaseCommand(1, 10); $filtersForm = new FilterSolvesForm("solvesFilterForm"); if ($filtersForm->isValid()) { // DevUtils::prettyPrintObject($filtersForm->getValue('tournamentType')); // $command->addFilter('tournamentType', $filtersForm->getValue('tournamentType')); } $filtersForm->showForm(true); $command->execute(); $solves = $command->getPaginatedSolves(); Twig::render('browse-solves', [ 'paginatedSolves' => $solves, 'filtersForm' => $filtersForm, ] );
-
OK - code examples first, just because they caught my eye immediately: It's missing the closing ")" and I also think it would look cleaner on one line: <!-- Render simple breadcrumb nav --> <ul class="breadcrumbs"> <?= $page->parents->each( '<li><a href="{url}">{title}</a>' ?> </ul> ie: <!-- Render simple breadcrumb nav --> <ul class="breadcrumbs"> <?= $page->parents->each('<li><a href="{url}">{title}</a>') ?> </ul> This won't work because of $p->url in double quotes like that without extra single quotes for href. // Render primary navigation foreach($pages->get("/")->children as $p) { echo "<a href="$p->url">$p->title</a> "; } Missing the semi-colon at the end of the second line: // Find and list tall buildings $buildings = $pages->get("/buildings/"); $skyscrapers = $buildings->find("height>1000") echo $skyscrapers->each("<li>{height}: {title}");
-
Hey all! This is a module to enhance forms built using the Pro FormBuilder module by providing the ability to submit them in place using AJAX and HTMX. FormBuilderHtmx works in harmony with FormBuilder by handling front-end rendering and AJAX and lets FormBuilder manage form configuration and processing. FormBuilderHtmx provides a drop-in replacement for the $forms->render() method and provides all native features and behavior (and adds a few extra superpowers to boot). Noteworthy features: Zero configuration, install and render AJAX powered FormBuilder forms immediately Render multiple forms on the same page. Supports both multiple instances of the same form or different forms. Each form is processed independently. Non-intrusive, can be used alongside FormBuilder's native rendering methods and does not modify core module behavior Perfect for forms embedded in popups and modals Does not conflict with styling and other JavaScript already in-place, only handles the form submission/response loop Automatically disables the `Submit` button on submission to prevent duplicate requests Provides the ability to add a custom 'spinner' shown when a form is being processed Gives you the ability to add additional HTML attributes to your FormBuilder <form> element. Add additional custom functionality using HTMX attributes, hook into form actions with your JavaScript, or even add AlpineJS directly to your forms. Compatible with FieldtypeFormSelect, let users choose which forms to embed, your code determines how they are rendered Uses HTMX, a stable, powerful, and tiny (14kb gzipped) library, installation documentation available here This module is BYOH (Bring Your Own HTMX) in that the HTMX library is not included or available within this module. This ensures long-term stability by not locking FormBuilderHtmx to external asset versioning. FormBuilderHtmx uses stable core HTMX features so use the library version that works for you and confidently add this module to both new, existing, and future ProcessWire applications. In some instances CSRF protection may need to be disabled to submit forms with this module. Just test your forms and you're good to go. Using this module is truly easy. <!-- Replace the native $forms->render() method with $htmxForms->render() --> <?php $htmxForm = $htmxForms->render('your_form_name') ?> <!-- Use native ProcessWire properties and methods as usual --> <?php echo $htmxForm->styles; echo $htmxForm->scripts; echo $htmxForm; ?> Presto. You can optionally include a helpful 'spinner' or activity animation that will be showed to users while their form request is being processed. Check out these ready-to-go examples you can use in your projects. <style> /* Add these styles to your CSS, the `.htmx-request` must be present as shown here. Be sure to include any CSS your 'spinner' may need, and style everything as desired */ .activity-indicator { display: none; } .htmx-request .activity-indicator, .htmx-request.activity-indicator { display: block; } </style> <!-- Optional second argument matches that of the $forms->render() method for pre-populated values The third argument is the CSS selector matching your 'spinner' element --> <?= $htmxForms->render('your_form_name', [], '#indicator-for-the-form') ?> <div id="indicator-for-the-form" class="activity-indicator"> <span class="spinner"></span> </div> Presto (again) Check out the documentation for detailed usage and other available features. Pull requests and issues filed on Github are welcome, or drop by here to get some help! Install as a ProcessWire module Install using Composer Download from the FormBuilderHtmx Github repository . Cheers!
- 29 replies
-
- 26
-
-
-
- formbuilder
- ajax
-
(and 1 more)
Tagged with:
-
I am using ProcessWire as the backend for an online shop system, which fetches the content as JSON files. The processwire installation has some legacy template code, which causes the startpage of the shop to require 3 or 4 actual ProcessWire pages. The JSON files are saved into a custom cache folder. When this cache is deleted, it has to be rebuilt. To achieve that, I implemented a Hook into PageRender::renderPage, which saves the currently viewed page and all of its language variants into JSON files. To get the actual markup, I am using $page->render(). Doing that, I noticed, that ProcessWire seems to prevent the currently requested page from also being generated (a second time) via $page->render(). The return value of $page->render() was always empty within the PageRender::renderPage Hook if $page was identical to the page of the current request. And it always returned the correctly rendered markup, if the current page was not identical to the Page in the $page->render() call. I assume that this has something to do with a mechanism in ProcessWire which shall prevent infinite loops. Does anybody know more about this? Are there any workarounds? Update: The issues were solved by cleaning up legacy template code – especially missing namespaces.
-
Hi, I'm in the process of relaunching a site of mine and wanted to build and test it side by side with the current site. I tried to set the template folder in ready.php for some users with $config→setLocation() to a different folder (as described here): $userNamesWithDevAccess = ['testuser']; if(in_array($user->name, $userNamesWithDevAccess)) { $config->setLocation('templates', 'site/templates-dev/'); echo '<pre>'; var_dump($config->urls->templates); var_dump($config->paths->templates); echo '</pre>'; } This seems to work as intended: string(21) "/site/templates-dev/" string(54) "/Users/myaccount/mysite/site/templates-dev/" But when I go to my frontend, there's only a blank page besides my var_dump. (Same blank page when I remove the var_dump test.) If I go to the backend I get the following error message: Hey now… Error: Exception: Missing or non-readable template file: site/templates-dev/site/templates/admin.php (in wire/modules/PageRender.module line 584) #0 wire/core/Wire.php (416): PageRender->___renderPage(Object(HookEvent)) #1 wire/core/WireHooks.php (968): Wire->_callMethod('___renderPage', Array) #2 wire/core/Wire.php (484): WireHooks->runHooks(Object(PageRender), 'renderPage', Array) #3 wire/core/WireHooks.php (1094): Wire->__call('renderPage', Array) #4 wire/core/Wire.php (484): WireHooks->runHooks(Object(DefaultPage), 'render', Array) #5 wire/modules/Process/ProcessPageView.module (193): Wire->__call('render', Array) #6 wire/modules/Process/ProcessPageView.module (114): ProcessPageView->renderPage(Object(DefaultPage), Object(PagesRequest)) #7 wire/core/Wire.php (416): ProcessPageView->___execute(true) #8 wire/core/WireHooks.php (968): Wire->_callMethod('___execute', Array) #9 wire/core/Wire.php (484): WireHooks->runHooks(Object(ProcessPageView), 'execute', Array) #10 index.php (55): Wire->__call('execute', Array) #11 {main} (I modified the line 584 in PageRender.module to output the whole path.) So looking at the path (site/templates-dev/site/templates/admin.php), it seems the system prepends the new path to the old path. Which is probably also the reason for the blank pages at the frontend. Is this a bug, or am I doing something wrong? Thanks! ProcessWire 3.0.246
-
Process Render File A Process module that renders markup from files in /site/templates/ProcessRenderFile/. This provides an easy way to create simple admin screens where it might be overkill to create a dedicated Process module for the purpose. Process page When you install the module a page with the name "render-file" and the title "Render File" is created under Setup. To change the page name or title, expand Page List to Admin > Setup > Render File and open the page for editing. Tip: if you create a new text field with the name "page_icon" and add it to the core "admin" template you can set a custom menu icon for the page by entering the icon name into the field. E.g. enter "smile-o" to use a smiley icon for the page. If you want to use ProcessRenderFile for more than one Process page you can create a new page under Setup. Select "admin" for the template, enter a title for the page, and in the next step choose ProcessRenderFile in the Process dropdown. Render files for URL segments On install the module will create a "ProcessRenderFile" folder in /site/templates/. Any .php files you save to this folder will be rendered as the output of a matching URL segment for Process pages using ProcessRenderFile. For example, if you create a file foo.php containing code... echo "This is the output of foo.php"; ...then you'll see this output when you visit /processwire/setup/render-file/foo/ (assuming the default ProcessWire admin page name and the default ProcessRenderFile page name). In the render file you can use all the ProcessWire API variables like $pages, $input, etc, as you would in a template file. If you create foo.js and foo.css (or foo.scss if you have ProCache installed) then those assets will be automatically loaded when you visit /processwire/setup/render-file/foo/. When a file is rendered the filename will be converted into a capitalised format that's used as a browser title and a headline. If you want to set a custom browser title and/or headline you can do this in your render file: $this->wire('processBrowserTitle', 'Custom browser title'); $this->wire('processHeadline', 'Custom headline'); Render file for the Process page If you create a render file that has the same name as the ProcessRenderFile Process page then this file will be rendered when the Process page is viewed without any URL segment. So for the default ProcessRenderFile page name you would create render-file.php. Note that this will override the default list output described below. Configuration The module configuration screen lets you select URL segment render files to appear as menu items. The selected render files will appear in the flyout menu for the Process page, and also as a list when the Process page is viewed without any URL segment. The list is only shown if you haven't created a render file for the Process page as described above. If you've created more than one ProcessRenderFile Process page then you'll see menu options for each page in the module configuration. https://github.com/Toutouwai/ProcessRenderFile https://processwire.com/modules/process-render-file/
-
Hi I intended to test RockPageBuilder with a fresh site-rockfrontend profile and most Rock-Modules. I installed page-edit-front and adjusted the profile in Rockfrontend to rockpagebuilder. Where to put the following render <?= $rockpagebuilder->render(true) ?> I tried to set it in different php/less files in /site/templates with this profile. Many thanks for a hint.
-
Feature request: a shouldRender() method for blocks
FireWire replied to FireWire's topic in RockPageBuilder
Here is what I'm currently doing: <?php class MyBlock extends Block { // ...rest of block /** * Determines if this block should render on the page * @return bool */ public function shouldRender(): bool { // For a field that displays featured activities. This is actually much more complex in real life // and keeping this in a shouldRender() method makes the template much cleaner return $this->featured_activities->where('date>=now&is_sold_out=false')->count(); // Sometimes blocks are saved in an incomplete state // Because ProcessWire doesn't have live field dependencies, an event has to be selected, page saved, // then activies in that event can be selected. This block shouldn't render until all of the information is complete. return !!$this->title && !!$this->event?->id && $this->featured_activities->count(); } // ...rest of block } View file: <?php namespace ProcessWire; /** @var Page $page */ /** @var MyBlock $block */ // This could be eliminated by making shouldRender() a method in Block.php if (!$block->shouldRender()) { return; } ?> <section class="rpb-myblock <?=$block->classes()?>" <?=alfred($block)?>> <!-- Block markup --> </section> If shouldRender() is defined in Block.php then it would be available everywhere. Otherwise to maintain consistency I have to do this in every block: <?php class AnotherBlock extends Block { // ...rest of block /** * This could be eliminated by making shouldRender() a method in Block.php */ public function shouldRender(): bool { return true; } // ...rest of block } -
Feature request: a shouldRender() method for blocks
FireWire replied to FireWire's topic in RockPageBuilder
@bernhard Forgot to mention that the first block of code is added to Block.php and is a method provided just for child blocks to override if they need. This way RPB will not render a block if that method returns false independently of the Inputfield UI for hide/unpublished state, which I think is what your for loop checks for. If I'm misunderstanding your for loop example then that could be my problem. A block can be published and unhidden, but the block can determine if it will render with its own logic. -
@Ana To add that type of user-facing functionality would best be achieved using AJAX. I think that this is a perfect use case for htmx which works very well with ProcessWire and is probably the fastest and easiest method to get the type of behavior you're looking for. Here's a working example of what this would look like. It takes about 5 minutes and you don't even have to leave your template file. <!DOCTYPE html> <html lang="en"> <head> <title><?=$page->title?></title> </head> <body> <!-- ...the rest of your template markup --> <!-- Your button to load more pages --> <div> <button hx-get="<?=$page->url?>?content=remaining-pages" hx-target="#remaining-pages-container" hx-select="#remaining-pages"> View More </button> <div id="remaining-pages-container"> <!-- Your additional page markup will be loaded here --> </div> </div> <!-- This page list will only render if the URL has ?content=remaining-pages appended --> <?php if ($input->get->content === 'remaining-pages'): ?> <ul id="remaining-pages"> <li>Remaining Pages</li> <?php foreach ($pages->find('your=selector,goes=here') as $remainingPage): ?> <li> <h2><?=$remainingPage->title?></h2> <a href="<?=$remainingPage->url?>">View Page</a> </li> <?php endforeach ?> </ul> <?php endif ?> <script src="https://unpkg.com/htmx.org@2.0.4" integrity="sha384-HGfztofotfshcF7+8n44JQL2oJmowVChPTg48S+jvZoztPfvwD79OC/LTtG6dMp+" crossorigin="anonymous"></script> </body> </html> Explanation. Having added the htmx script tag to your document, the htmx library is available. Here's what happens: Clicking the "View More" button makes an AJAX request to the server The URL for the hx-get attribute has been appended with "?content=remaining-pages", this can be anything you prefer The conditional block for additional pages will only render if the ProcessWire $input->get->content matches the GET variable we appended to the hx-get attribute URL When the page is rendered and response sent back for the AJAX request, htmx finds the element with the id 'remaining-pages' If an element with the id of 'remaining-pages' is found, then the contents of that element are inserted into an element with the id of 'remaining-pages-container' which is specified in the hx-target attribute of the <button> element There are some other ways that you could organize your code and return the markup, that's entirely up to you and how you would like to organize that in your ProcessWire site. This works, but we can make this more efficient. In the example above, the entire page is rendered just to get the remaining pages. This may not be an issue for all websites, but if a page has a lot of fields or other features that make database calls, then there is a lot of work being done on the server to render content that won't be shown because htmx is only selecting the content inside the element with the id of 'remaining-pages'. Here's an improvement: <!-- This page list will only render if the URL has ?content=remaining-pages appended --> <?php if ($input->get->content === 'remaining-pages'): ?> <ul id="remaining-pages"> <li>Remaining Pages</li> <?php foreach ($pages->find('your=selector,goes=here') as $remainingPage): ?> <li> <h2><?=$remainingPage->title?></h2> <a href="<?=$remainingPage->url?>">View Page</a> </li> <?php endforeach ?> </ul> <?php return; ?> <?php endif ?> <!DOCTYPE html> <html lang="en"> <head> <title><?=$page->title?></title> </head> <body> <!-- ...the rest of your template markup --> <!-- Your button to load more pages --> <div> <button hx-get="<?=$page->url?>?content=remaining-pages" hx-target="#remaining-pages-container" hx-select="#remaining-pages"> View More </button> <div id="remaining-pages-container"> <!-- Your additional page markup will be loaded here --> </div> </div> <script src="https://unpkg.com/htmx.org@2.0.4" integrity="sha384-HGfztofotfshcF7+8n44JQL2oJmowVChPTg48S+jvZoztPfvwD79OC/LTtG6dMp+" crossorigin="anonymous"></script> </body> </html> This is the exact same code as above, but here's what we did differently this time. The markup for the additional pages that only renders if 'content=additional-pages' is present has been moved above all of the other markup in the template After the closing <ul> tag and within the <?php endif ?> statement, we've added a return statement that prevents ProcessWire from rendering the rest of the page Depending on how "heavy" your template is, this could make the results appear to the user faster and very little work was needed on our part to do that. There are things that you can explore to make use of other ProcessWire features and improve the readability and/or reusability of your code Rather than using a GET variable, you could choose to use URL segments in ProcessWire to create and respond to a more natural URL You could use the render feature of FileTools in ProcessWire to store your remaining pages markup in a separate file You could use a GET variable such as "count=6" to set the number of pages to return rather than hard coding it Those are entirely optional, the example above is all you need to implement the feature you are looking for. Some notes on htmx If you use a build tool and npm, you can add htmx to your project as a package rather than the <script> tag htmx offers an easy way to create a 'loading' animation to let your users know that the button is retrieving the remaining pages while the AJAX request is being processed Hope this is useful for your project! The code example really did take only 5 minutes (maybe less!), without one line of JavaScript. If you prefer using a JavaScript oriented approach with JSON and markup such as the <template> tag as @TomPich mentioned, the same thing could be achieved using Alpine.js which is an easy way to add enhancements to your templates without the need for a full front end framework (just another personal favorite).
-
Migrating to ProcessWire Commerce from Padloper
Claus replied to kongondo's topic in ProcessWire Commerce (Padloper) Support
Just tried to upgrade my very old Padloper installation. I get this error when the `ProcessWireCommerce` folder i in the `modules` folder and I hit Modules > Refresh. Warning: require(ProcessWire/PaymentPaypal.php): Failed to open stream: No such file or directory in /yadayada/site/modules/ProcessWireCommerce/vendor/autoload.php on line 49 Well well… Fatal Error: Uncaught Error: Failed opening required 'ProcessWire/PaymentPaypal.php' (include_path='.:/Applications/MAMP/bin/php/php8.3.14/lib/php') in site/modules/ProcessWireCommerce/vendor/autoload.php:49 #0 [internal function]: ProcessWireCommerce\autoload_paypal_stripe('\Pay...') #1 wire/core/ModulesFiles.php (271): ReflectionClass->__construct('\\\Pa...') #2 wire/core/Modules.php (2276): ModulesFiles->getModuleFile('PaymentPaypal', Array) #3 wire/core/ModulesInfo.php (1128): Modules->getModuleFile('PaymentPaypal', Array) #4 wire/core/Modules.php (1953): ModulesInfo->clearModuleInfoCache(true) #5 wire/core/Wire.php (416): Modules->___refresh(true) #6 wire/core/WireHooks.php (998): Wire->_callMethod('___refresh', Array) #7 wire/core/Wire.php (484): WireHooks->runHooks(Object(Modules), 'refresh', Array) #8 wire/modules/Process/ProcessModule/ProcessModule.module (389): Wire->__call('refresh', Array) #9 wire/core/Wire.php (413): ProcessModule->___execute() #10 wire/core/WireHooks.php (998): Wire->_callMethod('___execute', Array) #11 wire/core/Wire.php (484): WireHooks->runHooks(Object(ProcessModule), 'execute', Array) #12 wire/core/ProcessController.php (361): Wire->__call('execute', Array) #13 wire/core/Wire.php (413): ProcessController->___execute() #14 wire/core/WireHooks.php (998): Wire->_callMethod('___execute', Array) #15 wire/core/Wire.php (484): WireHooks->runHooks(Object(ProcessController), 'execute', Array) #16 wire/core/admin.php (174): Wire->__call('execute', Array) #17 wire/modules/AdminTheme/AdminThemeUikit/controller.php (15): require('/Users/claus/Gi...') #18 site/templates/admin.php (15): require('/Users/claus/Gi...') #19 wire/core/TemplateFile.php (328): require('/Users/claus/Gi...') #20 wire/core/Wire.php (413): TemplateFile->___render() #21 wire/core/WireHooks.php (998): Wire->_callMethod('___render', Array) #22 wire/core/Wire.php (484): WireHooks->runHooks(Object(TemplateFile), 'render', Array) #23 wire/modules/PageRender.module (581): Wire->__call('render', Array) #24 wire/core/Wire.php (416): PageRender->___renderPage(Object(HookEvent)) #25 wire/core/WireHooks.php (998): Wire->_callMethod('___renderPage', Array) #26 wire/core/Wire.php (484): WireHooks->runHooks(Object(PageRender), 'renderPage', Array) #27 wire/core/WireHooks.php (1099): Wire->__call('renderPage', Array) #28 wire/core/Wire.php (484): WireHooks->runHooks(Object(Page), 'render', Array) #29 wire/modules/Process/ProcessPageView.module (193): Wire->__call('render', Array) #30 wire/modules/Process/ProcessPageView.module (114): ProcessPageView->renderPage(Object(Page), Object(PagesRequest)) #31 wire/core/Wire.php (416): ProcessPageView->___execute(true) #32 wire/core/WireHooks.php (998): Wire->_callMethod('___execute', Array) #33 wire/core/Wire.php (484): WireHooks->runHooks(Object(ProcessPageView), 'execute', Array) #34 index.php (55): Wire->__call('execute', Array) #35 {main} thrown (line 49 of site/modules/ProcessWireCommerce/vendor/autoload.php) This error message was shown because: you are logged in as a Superuser. Error has been logged. -
The language of $user->language (guest) is not correctly
psy replied to Dennis Spohr's topic in General Support
I'm experiencing a similar issue. The default language is English. The other language is French. Even when I set the guest user language to French in the user profile, it defaults to English on render. How do I get PW to recognise the guest user language? -
hi @bernhard, trying to set up RPB 5.5.4 in PW 3.0.240 there's no working site "out of the box" after installation, regardless the site template i use. <div id="content"> Homepage content <?php echo $rockpagebuilder->render() ?> </div> gives the mentioned error Fatal Error: Uncaught Error: Call to a member function render() on string in C:\wamp64\www\oh1\site\modules\RockFields\RockPageBuilder.module.php:1535 Stack trace: #0 C:\wamp64\www\oh1\site\templates\home.php(18): RockPageBuilder->render() #1 C:\wamp64\www\oh1\wire\core\TemplateFile.php(328): require('C:\\wamp64\\www\\o...') #2 C:\wamp64\www\oh1\wire\core\Wire.php(413): TemplateFile->___render() #3 C:\wamp64\www\oh1\wire\core\WireHooks.php(968): Wire->_callMethod('___render', Array) #4 C:\wamp64\www\oh1\wire\core\Wire.php(484): WireHooks->runHooks(Object(TemplateFile), 'render', Array) #5 C:\wamp64\www\oh1\wire\modules\PageRender.module(581): Wire->__call('render', Array) #6 C:\wamp64\www\oh1\wire\core\Wire.php(416): PageRender->___renderPage(Object(HookEvent)) #7 C:\wamp64\www\oh1\wire\core\WireHooks.php(968): Wire->_callMethod('___renderPage', Array) #8 C:\wamp64\www\oh1\wire\core\Wire.php(484): WireHooks->runHooks(Object(PageRender), 'renderPage', Array) #9 C:\wamp64\www\oh1\wire\core\WireHooks.php(1094): Wire->__call('renderPage', Array) #10 C:\wamp64\www\oh1\wire\core\Wire.php(484): WireHooks->runHooks(Object(HomePage), 'render', Array) #11 C:\wamp64\www\oh1\wire\modules\Process\ProcessPageView.module(184): Wire->__call('render', Array) #12 C:\wamp64\www\oh1\wire\modules\Process\ProcessPageView.module(114): ProcessPageView->renderPage(Object(HomePage), Object(PagesRequest)) #13 C:\wamp64\www\oh1\wire\core\Wire.php(416): ProcessPageView->___execute(true) #14 C:\wamp64\www\oh1\wire\core\WireHooks.php(968): Wire->_callMethod('___execute', Array) #15 C:\wamp64\www\oh1\wire\core\Wire.php(484): WireHooks->runHooks(Object(ProcessPageView), 'execute', Array) #16 C:\wamp64\www\oh1\index.php(55): Wire->__call('execute', Array) #17 {main} thrown as i am not able to setup RPB at all i wonder if PW 3.0.240 has an error (or - more likely - me myself & I)