Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 10/27/2022 in all areas

  1. Good day, community! I have found another great opportunity to support PW ecosystem - just look here! This is @teppo's sponsorship page. He is doing such a load of super cool and useful things, that sponsoring him is a sure must))) Please start throwing your money at this fine gentleman)) Pitifully I cannot do it myself now easily, but I'll find a way. I almost feel guilty for not paying for Wireframe)) I've updated my other post with the modules' authors accepting donations list - just in case. You can check other great sponsorship chances there.
    5 points
  2. Hey @teppo finally 😉 Hope you enjoy it! Here you go: https://packagist.org/packages/baumrock/rockmigrations Let me know how it goes
    2 points
  3. GistPad Manage your code snippets and developer notes using GitHub Gists and repositories. https://marketplace.visualstudio.com/items?itemName=vsls-contrib.gistfs Stumbled upon this today. I have watched the demo below by the creator. This is a really awesome tool! Other features include creating code documentation/notes, create code playgrounds right within VSC, interoperates with codepen, etc. Watch the video below, right to the end. Quality is not the best (it was a live stream) but it is worth it.
    2 points
  4. Github: https://github.com/thetuningspoon/AdminPreSaveValidation This module prevents admin editors from saving changes to a page that has one or more invalid fields. It uses an ajax call to check for errors and javascript to populate the page edit form with any error messages that were returned. This way the user can correct the issues and resubmit the form without invalid data getting saved to the database or the editor losing changes. I've wanted a way to implement this common workflow in ProcessWire for some time now and this relatively simple ajax-based approach makes it possible without getting too much in the way of how ProcessWire normally works. For example, all of the post-save actions (Save + Exit, Save + View, etc.) still work as usual. The only downside is that a successful save will take a bit longer as it involves two sequential http requests (the initial ajax request that checks for errors and the normal page submit after no errors are returned). This module has also been tested successfully with repeaters and other nested inputs. By hooking after Inputfield::processInput, you can add your own custom validations to inputfields and this module will pick up on and display them as well. /* * Example of hook that adds an error to an inputfield. This will add an error to every input. */ $this->wire()->addHookAfter("Inputfield::processInput", function(HookEvent $event) { $event->object->error('Invalid input!'); }); I hope others will find this module useful!
    1 point
  5. Hey @teppo! I am running circles around this module for a long time. And last week did install it on a dev env for the 1st time. I am not quite sure how to integrate it in my workflow. And not sure my workflow fits it (not the other way around))) Please write back about your experience with RockMigrations if you progress with using it. Your opinion and feedback are a really valuable!
    1 point
  6. Hey @bernhard, I'm considering RockMigrations for a new project, but would very much prefer to install it via Composer to avoid bundling module code with project code, make updates easier, etc. I noticed that your old RockMigrations project had a composer.json in place, so would you mind adding that here as well, and preferably also submitting the package to packagist.org? Thanks in advance! 🙂 Note that I would recommend using the options outlined here: ... instead of hari/pw-module. The installer plugin from Hari was updated a while ago to support Composer 2, but it still lacks support for custom modules directory, for an example. In my opinion it would be best to eventually migrate modules to use composer/installers, since that's the "official" solution.
    1 point
  7. Because I have dozens of PW projects on the go (I really must tidy up my code folder) I didn't want to include the core files for each projects. The best solution I managed was to have a single copy of the core files in a folder which I then add to the intelephense environment path settings: "intelephense.environment.includePaths": [ "/Users/stephen/code/stubs/", "/home/stephen/code/stubs/" ], It would be great to have PW stubs in the core Intelephense list but I have no idea how to even start going about that.
    1 point
  8. Great catch! Some users have reported this in the past but never managed to nail it down to PagePaths! I'll have a play and get back to you. Thanks!
    1 point
  9. @Robin S I just wanted to post back and confirm that now I know not to look for ___upgrade() method firing on module refresh alone I can see everything working exactly as you described. Thanks all. 🙂 An aside - I wonder if the wording here would be better as 'applied when each module is next loaded' just to clarify that the refresh itself doesn't guarantee a module loading... although it may just be me that made this mistake!
    1 point
  10. @Martinushas summed it up pretty well. This is basically the same approach I use. So you build your navs/links up using your category (or sub page names) rather than a 'traditional' link to a sub-page url and append them to the parent page URL. <a href="<?=$page->url.{CAT-NAME-GOES-HERE};?>">Example Category</a> Then you can get retrieve the url segment from the page URL and use it in your selectors for filling out the dynamic content.
    1 point
  11. I changed my code to use wireInstanceOf(). Works like a charm. Today another problem surfaced. The MM Settings do not get saved when the core module PagePaths is installed. Located the cause in ProcessMediaManager.module L156 $mediaManagerSettings = $this->wire('pages')->get("template=media-manager-settings, parent={$path},include=hidden")->media_manager_settings; When PagePaths is not installed, the selector returns the page under Admin->Media Manager->Media Manger:Settings just fine. But with PagePaths installed it returns a NullPage. I found that with PagePaths installed page paths change to also include the language name, but not consistently. My install sets the home URL for the default language to "mydomain.com/en/". The paths that are returned look like $pages->get('template=media-manager-settings')->path // "/en/processwire/media-manager/media-manager--settings/" (note the '/en/' at the beginning). $pages->get('name=media-manager')->path // "/processwire/media-manager/" $config->urls->admin // "/processwire/" There is the inconsistency. Pages with template admin do not have the language prepended while pages with other templates do. Guess this implementation makes sense. When I remove "parent={$path}" from the selector, it works with PagePaths installed. I implemented a quickfix like this /******** - MEDIA MANAGER SETTINGS - *******/ $path = $config->urls->admin . 'media-manager/'; $selector = "template=media-manager-settings, status<" . Page::statusTrash; if(!$this->wire('modules')->isInstalled('PagePaths')) $selector .= ", parent={$path}"; $mediaManagerSettings = $this->wire('pages')->get($selector)->media_manager_settings; I left out the "include=hidden" since $pages->get() returns hidden pages by default. Is "parent={$path}" needed at all, can there be situations where multiple pages with template media-manager-settings are present in the system? Maybe in the Trash. So I handled that situation. Please let me know what you think. Thank you.
    1 point
  12. Thanks for responding all. I think I actually have the same as @Guy Incognito My page structure now is (order not important): Home - Departments (parent with each department in it) - Categories (parent with each category in it) - Sellers (parent with each seller in it) - Brands (parent with each brand in it) - Products (parent with each product in it) I use 1 template (browse) for determining what link was clicked (switch case, declaring variables), and 1 template (product) for a single product. In my browse template I include one of two files: for Products or for parents. With markup and all. My browse template is used for all parents and their children. The only thing is, I need occasional dropdown selects with values that are occupied with products. And if I use a direct query on Departments it would be easy but I need only those which have products (I hate pages that says 'nothing found' 😉 I solve this with the following example (some parts can be merged but for simplicity I type it like this): // DEPARTMENT SELECT $select2 = $pages->find("parent=/products/, department>0, sort=name"); // create new array $array2 = array(); // loop through results foreach($select2 as $item) { // move each department in new array array_push($array2, $item->department); // place only unique values in variable $totalDepartments = array_unique($array2); } And then I thought, maybe it was easier moving categories under departments, and products under categories. But maybe I just have to leave it as it is.
    1 point
  13. @Guy Incognito Your above explanation on url segments is very interesting. Can you expand any further on how you set this up? I've read through https://processwire.com/docs/front-end/how-to-use-url-segments/ , but I'm still not fully absorbing what I think is your approach. I'm sure the parent could benefit from this approach as well.
    1 point
  14. @msavard You add custom styles by editing the CK Editor JS file which (from memory) is located at something like /site/modules/InputfieldCKEditor/mystyles.js. But you may wish to first check out this thread as there is a new RTE incoming for ProcessWire 🙂
    1 point
  15. @Martinusif I understand what you're trying to do correctly, I think url segments are the best approach. I frequently use ProcessWire for organising and displaying categorised data and usually approach this sort of thing with url segments rather than working with the actual pages (if that makes sense). So put all your items under a /items page rather than in a set structure. You can then you can create category pages as views of different sub pages by using the url segments in your selector. The advantage is that you can have your items in multiple categories without any duplication of pages, you only have to maintain one parent 'category' template and from an SEO perspective the url segments appear the same as regular URLs. (You may need to manually inject them into your sitemaps though).
    1 point
  16. I mean… it’s always going to be departments/<some department>/<some category>/, right? So when you navigate to a catetory page such as your example /sitename/departments/hardware/heating/, you want to see products that have both department=hardware and category=heating? Do you use the same template for sellers, brands, categories and departments? It would be easy if you had a specific category template. Otherwise you have to go by position in the page tree: if ($page->matches('has_parent=departments')) { // you could also use $page->rootParent if /departments/ is immediately below root //now $page may be either a department or a category. we assume //that /departments/ has ONLY departments as children, and all //such departments have ONLY categories as children (or perhaps //they have things that don’t run this template) if ($page->parent->name === 'department') $items = $pages->find("parent=/products/, department=$page, sort=$order, limit=4"); else $items = $pages->find("parent=/products/, department=$page->parent, category=$page, sort=$order, limit=4"); $file = "_products.php"; } else { //sellers and brands }
    1 point
  17. Thanks for reporting. Looks like a rookie mistake on my part. Good solution. I'll probably use wireClassName() or wireInstanceOf().
    1 point
  18. When your blog content is growing to some thousands of pages and you have comments scattered here and there, sometimes you start wondering if placing comments below each post is the best approach. Of course this totally depends on your project and contents. In my case I came to the conclusion I could provide a better user experience switching to a Forum-like solution, where discussions were organized by macro subjects and not below each individual post. Of course there are many products and services providing fully featured forum solutions, but getting only few comments per day I was reluctant to setup a dedicated forum and to deal with users' profiles. A nice thing of the comments system is that users do not need to create account and password, but simply use their email address. And here we are ... why not to setup a very basic Forum-like solution using PW Comments? But please do not get too excited… we will just use comments in a way that looks-like-a-forum. I think this solution makes sense if you have a limited number of comments per day spread on some topics. If you need to deal with high discussions traffic with several users ... do it with a fully featured forum solution !! To implement this Forum-like solution we will take benefits of (1) PW pages/templates flexibility (why you should be here otherwise…), (2) core module FieldtypeComments, (3) Uikit 3 Site/Blog Profile, (4) some of the tutorials I recently released about PW Comments (listed at the end). OK, let's start. Login into the Admin panel, select Setup, and then Fields. Let's create a checkbox field named "sticky" that we can use to keep some forum subjects on top of the communities. Now let's move to Setup, Template. We will create a new template with name "communities'. In addition to "title" field, we will add also "body" and "sidebarRight" fields (already available in the profile): Then we create a template, that we will use for individual communities, with name "community". In addition to "title" field, we will add "date", "body", "images", "comments" fields (already available in the profile) and the "sticky" field we have just created. If you wish, as I did, you can also associate some category fields. If you use Multi-Language is a good idea to use the field "date", as ,differently from createdStr, it will automatically return a locale-formatted date as you defined in the field. Now that we have created the templates, we need to customize them. Reopen the "communities" template. In the Family tab: allow the template to have children, allow only one page with this template, select "community" as only allowed template for CHILDREN. Then in the URLs tab: select allow page numbers. This will return a paginated list of communities. We reopen the "community" template. In the Family tab: do not allow the template to have children, allow to create new pages, select "communities" as only allowed template for PARENT. Now in the URLs tab: select allow page numbers. This will be necessary to create paginated comments. Let's go to the page-tree, under Home we will create a new page named "Community" using the templates "communities" (note the final s), this will be the page listing all the communities. Under the Community page, we will create the individual communities. Give the pages the name you wish and use the template "community" (note w/o the final s). It may be good creating one with the name "New Forum Requests" checking its "sticky" field so that it remains on top. As to implement this Forum-like solution, the comments pagination is a must, at this stage you will have to implement it as described in this tutorial: Now we are ready for coding (very little!) the php templates. We need to associate php files to the two templates we have created. In site/templates create two new php files communities.php and community.php. Open the template blog.php and copy its content to communities.php, then repeat the same operation copying the content of template blog-post.php to community.php. Great! We are few steps away from our Forum-like solution. Modify communities.php as follows: ... echo ukHeading1(page()->title, 'divider'); echo page()->body . '<br><hr>'; //>>>>> ADD THIS LINE //$posts = page()->children('limit=10'); //echo ukBlogPosts($posts); $posts = page()->children('sort=-sticky, sort=title, limit=10'); //>>>>> ADD THIS LINE echo ukBlogPosts($posts, ['moreText' => '', 'moreIcon' => '']); //>>>>> ADD THIS LINE ... Then modify community.php as follows: // blog post content echo ukBlogPost(page()); // comments if($page->hasField('comments')) { //>>>>> ADD THIS LINE $comments = page()->comments; // comment list if(count($comments)) { //echo ukHeading3("Comments", "icon=comments"); echo ukComments($comments->find("sort=-created"), ['paginate' => true]); //>>>>> ADD THIS LINE - READ PAGINATION TUTORIAL (NEEDED) echo '<hr>'; } // comment form $gdpr = __('I agree with the processing of my personal data. I have read and accept the Privacy Policy.'); //>>>>> ADD THIS LINE - READ GDPR TUTORIAL (OPTIONAL) echo ukHeading3(__('Join the discussion'), "icon=comment"); echo ukCommentForm($comments, ['labels' => ['gdpr' => $gdpr]]); //>>>>> ADD THIS LINE - READ GDPR TUTORIAL (OPTIONAL) } //>>>>> ADD THIS LINE Very good (hope so...). Now let's see the result. When browsing to the Community page we will get the list of the communities. In my example I decided to keep sticky the one where users can submit suggestions for new forum subjects. Selecting one of the communities we have created, we are going to see (1) a description of the community, (2) a paginated list of comments, (3) and the comment form at the bottom. Please note that in this picture pagination is kept with a limit of three items just to fit the image … It makes sense to have 10-15-20 comments per page depending on your preferences. And we are done, here it is. If you wish you can implement some additional features as described in the tutorials below. Not mandatory but probably makes good sense to enable the honeypot field as described in this tutorial as anti-spam measure: If you have the "pleasure" to deal with GDPR matters, here is described how to add a privacy checkbox to your comment form: and finally if you wish your Forum-like solution to be Multi-Language here it is what to do: I hope you enjoyed and wish you a nice week-end ! PS: it's a couple of tutorials I miss the emoj … hope they will come back in this forum soon !!
    1 point
  19. Hi everyone, I hope this hasn't been covered anywere else but I tried to search for this topic and I couldn't seem to be able to find anything. I'm fairly new to Processwire and I'm liking it a lot but I don't understand what could be the optimal way to do a little project I'm working on, in particular how to store user-submitted data. Basically I'm trying to build a checklist website where users can flag a list of items as "collected" so that they can keep track of what they have so far. I'm wondering what could be the best way of storing this user-dependant data. For now I've organized the site as follow: Every item is a page with specific fields (name, description ecc...) Every user has a custom field that's a list of items checked, and for this I used a page reference field On page load the site should check which items result as collected and tick the corrisponding checkbox The list of items is presented as a table where each row starts with a checkbox, this is not a checkbox field since if I would mark this as "checked" this would be associated with the item and not with the user resulting in the item being checked for all of them (correct me if I'm wrong). I'm struggling on how I can collect the data from the frontend (which checkoxes are marked) and edit the user field so that I can store them and retrieve it later on page load (depending on the account who is currently watching the checklist). I was thinking of putting a javascript listener on the checkboxes who calls a php function to set the corrisponding user value but this seems a little convoluted and I'm wondering if there could be a better way to handle this, something I'm not seeing right now. If you wanna take a look you can find the checklist here: https://valuvato.it/spells/sorceries/ (yes it's a collection of Elden Ring stuff so one can mark what he has already looted and what's missing in his gameplay). Any idea would be appreciated, even if it changes the architecture of the project, I'm using this to learn Processwire after all! Thanks in advance ?
    1 point
  20. Hi, in a recent project I had to import large amounts of data that got uploaded through the frontend. To avoid lags in the frontend I pushed the actual import work to processes in the background. Since timely resources for that project were limited, I resorted to a quite simple method of starting the workers public function startSalesImportWorker() { $path = $this->config->paths->siteModules . "{$this->className}/workers/"; $command = "php {$path}salesimportworker.php"; $outputFile = "{$path}/logs/workerlogs.txt"; $this->workerPid = (int) shell_exec(sprintf("%s > $outputFile 2>&1 & echo $!", "$command")); if ($this->workerPid) return $this->workerPid; return false; } Here's the worker code namespace ProcessWire; use SlashTrace\SlashTrace; use SlashTrace\EventHandler\DebugHandler; include(__DIR__ . "/../vendor/autoload.php"); include(__DIR__ . "/../../../../index.php"); ini_set('display_errors', false); error_reporting(E_WARNING | E_ERROR); $slashtrace = new SlashTrace(); $slashtrace->addHandler(new DebugHandler()); // $slashtrace->register(); $lockfile = __DIR__ . "/locks/lock-" . getmypid(); // restart when fail or done function workerShutdown($args) { // release lockfile if (file_exists($args['lockfile'])) unlink($args['lockfile']); echo PHP_EOL . "Restarting...\n"; $outputFile = __DIR__ . '/logs/workerlogs.txt'; $command = PHP_BINARY . " " . $args['command']; sleep(1); // execute worker again exec(sprintf("%s > $outputFile 2>&1 & echo $!", "$command")); } register_shutdown_function('ProcessWire\workerShutdown', array('lockfile' => $lockfile, 'command' =>$argv[0])); // wait for other workers to finish while (wire('files')->find(__DIR__ . "/locks/")) { sleep(5); } // create lockfile file_put_contents($lockfile, $lockfile); try { // ini_set('max_execution_time', 300); //300 seconds = 5 minutes wire('users')->setCurrentUser(wire('users')->get("admin")); echo "starting import: " . date('Y-m-d H:i:s') . PHP_EOL; /** @var \ProcessWire\DataImport $mod */ $mod = wire('modules')->get("DataImport"); $mod->importSales(); echo PHP_EOL . "Import finished: " . date('Y-m-d H:i:s'); // run only for 1 round, then start a new process: prevent memory issues die; } catch (\Exception $e) { $slashtrace->handleException($e); die; } I got the idea for restarting the same worker from https://www.algotech.solutions/blog/php/easy-way-to-keep-background-php-jobs-alive/ Note that I am using https://github.com/slashtrace/slashtrace for error handling since it gives nice CLI output. And I couldn't figure out how to utilize the native PW Debug class for that since I needed stack traces. Overall this solution worked quite well. But it doesn't give any control over the worker processes. At least there was no time to implement. Only after having finished the project, I discovered https://symfony.com/doc/current/components/process.html which seems to have everything you need to start and monitor background processes. So next time the need arises I will definitely give it a try. I'm imagining a Process module that lets you monitor/stop background workers and a generic module to kick them off. How do you handle background processes with PW?
    1 point
  21. This is what I am using: $this->wire->addHookAfter('ProcessPageEdit::getSubmitActions', function($event) { $page = $event->process->getPage(); if($page->template != "foo") return; $actions = $event->return; unset($actions['next']); $actions['clone'] = [ 'value' => 'clone', 'icon' => 'clone', 'label' => 'Save + create copy', ]; $event->return = $actions; }); $this->wire->addHookAfter('ProcessPageEdit::processSubmitAction', function($event) { $action = $event->arguments(0); // action name, i.e. 'hello' $page = $event->process->getPage(); // Page that was edited/saved if($page->template != 'foo') return; if($action === 'clone') { $copy = $this->wire->pages->clone($page); $copy->title .= ' (copy ' . uniqid() . ')'; $copy->save(); $this->wire->session->redirect($copy->editUrl); } });
    1 point
  22. "Markup Regions pw vs data-pw different behavior" I have not yet experienced such a behavior. Maybe you are mixing up "Boolean action attributes (inner HTML)" with "Action attributes with value (outer HTML)"? Regarding the differences between these two, see my explanation below. +1 Here is my simplified docs for markup regions, we can also call it "cheat sheet". I wrote it some time ago: Defining markup regions Basic region Wrapping tags do appear in the final markup. Children tags are preserved if not explicitly replaced. <div id="hello"> OR <div data-pw-id="hello"> data-pw-... They are removed from the final output and thus not visible to front-end markup, while id="..." is not removed! Placeholder region Only the inner HTML will be used and the wrapping tags won't appear in the final markup. <pw-region id="hello">...</pw-region> Good for groupping tags in the <head> eg.: <pw-region id="site_scripts"> Optional region It will be automatically removed from the document markup if nothing populates it, so it is a region which should be empty by default. <div id='hello' data-pw-optional></div> Examples: an <ul>, which [according to HTML5 specs] is required to have one or more <li> elements within it, otherwise it's invalid HTML. a sidebar which is only needed on pages populated with widgets /* -------------------------------------------------------------------------------------------------- */ Populating markup regions Available action attributes: data-pw-replace: replaces a region’s markup data-pw-append: appends markup to a region data-pw-prepend: prepends markup to a region data-pw-before: inserts markup before a region data-pw-after: inserts markup after a region Boolean action attributes (inner HTML) Only applies the inner HTML to the region. TARGET CODE: <div id='hello'> <h2> Hello World </h2> </div> <p data-pw-id="hello" data-pw-append> This text will APPEND to div#hello </p> <p data-pw-id="hello" data-pw-prepend> This text will PREPEND to div#hello </p> <p data-pw-id="hello" data-pw-before> This will insert this text BEFORE div#hello </p> <p data-pw-id="hello" data-pw-after> This will insert this text AFTER div#hello. </p> RESULTS: This will insert this text BEFORE div#hello <div id='hello'> This text will PREPEND to div#hello <h2> Hello World </h2> This text will APPEND to div#hello </div> This will insert this text AFTER div#hello Action attributes with value (outer HTML) All of the markup that you specify (the outer HTML) becomes part of the final document markup (except for the pw-* attributes): TARGET CODE: <div id='hello'> <h2> Hello World </h2> </div> <p data-pw-append="hello"> This paragraph will APPEND to div#hello </p> <p data-pw-prepend="hello"> This paragraph will PREPEND to div#hello </p> <p data-pw-before="hello"> This will insert this paragraph BEFORE div#hello </p> <p data-pw-after="hello" class="world"> This will insert this paragraph with class "world" AFTER div#hello. </p> RESULTS: <p> This will insert this paragraph BEFORE div#hello </p> <div id='hello'> <p> This paragraph will PREPEND to div#hello </p> <h2> Hello World </h2> <p> This paragraph will APPEND to div#hello </p> </div> <p class="world"> This will insert this paragraph with class "world" AFTER div#hello. </p> /* ------------------------------------------------ ------------------------------------------------ */ Adding HTML attributes Any HTML attribute you add to the action tag that does not begin with pw- or data-pw- will be added to the originally defined region tag. TARGET CODE: <ul id="foo" class="bar"> <li> First item </li> </ul> ACTION CODE: <ul data-pw-append="foo" title="Hello"> <li> Second item </li> </ul> RESULTS: <ul id="foo" class="bar" title="Hello"> <li> First item </li> <li> Second item </li> </ul> Adding and removing classes Classes from the action tag and the region tag are merged by default. To remove a class by the region action: prepend a minus sign to the class to be removed, eg: class="-foo bar" will result in class="bar"
    1 point
  23. Hi @abdus, Do you know if it's possible to use this technique to add config fields such as minWidth and maxWidth to the template context for InputfieldImage? My first attempt isn't working: // Add more image config fields to template context $this->addHookMethod('InputfieldImage::getConfigAllowContext', function (HookEvent $e) { $allowables = ['minWidth', 'minHeight', 'maxWidth', 'maxHeight']; $e->return = array_merge($e->return, $allowables); }); I have a feeling that the reason this doesn't work is because those config fields are inside a fieldset. Adding the whole fieldset would be fine, but the problem is that the fieldset doesn't have a name to add to getConfigAllowContext(). Any ideas? ----- EDIT: have sussed it out. I used another hook to give names to those fieldsets. // Give names to image config fieldsets $wire->addHookAfter('InputfieldImage::getConfigInputfields', function(HookEvent $event) { /* @var InputfieldWrapper $wrapper */ $wrapper = $event->return; $f = $wrapper->getChildByName('maxWidth'); $fieldset = $f->parent; $fieldset->name = 'maxDimensions'; $f = $wrapper->getChildByName('minWidth'); $fieldset = $f->parent; $fieldset->name = 'minDimensions'; }); // Add more image config fields to template context $this->addHookMethod('InputfieldImage::getConfigAllowContext', function (HookEvent $e) { $allowables = ['maxDimensions', 'minDimensions']; $e->return = array_merge($e->return, $allowables); });
    1 point
  24. Hi henrik, this problem comes from the fact, that there is no outputformatting when bootstrapping PW. therefore image fields are always arrays even if they are set to max = 1 and all your textformatters won't work. https://processwire.com/talk/topic/5375-image-paths-when-bootstrapping-pw/ regarding your ajax problem: you don't need to create a file outside your site folder! you have two options: 1) create a separate template only for ajax requests and also a page for that (eg hidden page /ajax) - then you can just call this page and return your content 2) return your ajax content from within the same file. if you are using delayed output strategy that's really easy. all you have to do is put something like this on top of your template file: if($config->ajax) { // do your ajax stuff here echo 'i am an ajax response'; die(); } // regular call $headline = '<h1>' . $page->title . '</h1>'; $content = $page->body; and so on... hope that helps! good luck
    1 point
  25. I'm just getting started and have looked for ways to update a page including its fields via a front-end form, but I'm missing a few pieces of the puzzle. Here's what I have, mostly borrowed from posts on this forum: $page = $pages->get('1015'); // get some page // make a form $form = $modules->get('InputfieldForm'); $form->method = 'post'; $form->action = './'; // add the page's fields to the form $form->add($page->getInputfields()); // add a submit button to the form $submit = $modules->get('InputfieldSubmit'); $submit->name = 'submit'; $form->add($submit); // process the form if it was submitted if($input->post->submit) { $form->processInput($input->post); $page->save(); echo '<p>saved</p>'; } // render the form output echo $form->render(); I think the problem is that I have to loop through the form inputs and save them individually? How would I do this?
    1 point
×
×
  • Create New...