-
Posts
1,306 -
Joined
-
Last visited
-
Days Won
13
Everything posted by Juergen
-
If you want to completely hide the field (not only closed) you have to set the display option to "open" and add the following condition:
-
Sorry that was a wrong information - I have corrected it. You have to use another option.
-
-
Hello @ all, I am trying to find a solution to change the table headers via a hook. These are the hooks that can be use with a pagetable field: The fields of the pagetable can be entered in the configuration of the pagetable field inside a textarea: I guess there should be a possibility to change the labels of these fields which are used inside the table header. Changing it directly at the fields is not an option in this case. My idea was to hook like this: addHookBefore('InputfieldPageTable::render', function($event) But I have no idea at the moment how to get the labels of the fields. Does anyone has a hint how it could be done?
-
Sometimes you want to add a specific markup to the values inside a pagetable field. Fe. you want to add a FontAwesome icon in front of the value or you want to add a background-color. In this little tutorial I want to show you how you can do that with only a view lines of code. In the following example I will add the background color red to a specific field inside the page table. This is what i looks like at default: After the manipulation it will looks like this: You can see the difference in the second field of the pagetable. This manipulation makes not really sense and it is only to show you what can be done. You can manipulate it also in other ways. Fe to add different colors to different status of orders and so on. To achive this we use the following type of hook: Fieldtype::markupValue (read more at https://processwire.com/api/ref/fieldtype/markup-value/) In this case we put the code inside the init.php and not in the ready.php. The reason for this is, that if the page table will be updated via Ajax, the default values will be displayed again if the code is in ready.php. So here we go: $this->addHookAfter('Fieldtype::markupValue', function($event) { $page = $event->arguments(0); $field = $event->arguments(1); $value = $event->arguments(2); if($field->name == 'nameofthefield' && $page->template->name == 'childrentemplatename') { $event->return = '<span style="background:red;color:#fff;">'.$value.'</span>'; } }); First we define all the variables needed for the manipulation ($page, $field and $value). $value returns the formatted value of the field. If you need the unformatted value (fe. if it is a date field and you want the timestamp) you get the unformatted value by using this line of code: $value = $page->getUnformatted($field->name); We restrict it to a special field of the pagetable called "nameofthefield" - rename it to the name of your field where you want the manipulation to take place. So this field of the pagetable is a field of a child template. In this case the child template is called "childrentemplatename". You have to rename it to your child template name. Only to clearify: each field inside the pagetable is part of a child page. "$event->return" returns the output of the field (usually the value). In this example the value of the field should be between two <span> elements with a special CSS styling to add a red background and turn the color of black to white. Here is a usecase where I use this technique: You can see that after the end date there is no time (in opposition to the start date). Instead of the time the text "no specific endtime" is displayed. This is because this event has no specific end time (it is open end). Only to mention: The editor can choose if the event is all day long or starts and ends on specific date and time or it is open end. Thats all and happy coding with your own manipulations!
-
Only to mention: I know that AOS is not full supporting the new UIKit Theme, but I think I post it nevertheless. With the new UIKit Theme the description of the fields that are usually shown inside an overlay will be displayed on the left side of the field too. The hover function works also. This is fe a description of a pagetable field. As you can see the description will be displayed in a small column on the left side. Best regards
-
Here is another working method, that only shows changes once after save. It is based on this post from Ryan. //Compare before and after values $pages->addHookAfter('saveReady', function($event) { $page = $event->arguments('page'); if(!in_array($page->template->name, array('template1', 'template2'))) return; //restrict it to these templates only $fields = array('field1','field2'); //check only changes on these fields $this->wire('pages')->uncache($page);//uncache new page $oldPage = $this->wire('pages')->get($page->id);// get old page $changedfieldsarray = array(); foreach($fields as $field) { if (($oldPage->$field) != ($page->$field)) { //this is the comparison between before and after $changedfieldsarray[] = $page->fields->get($field, true)->label; } } if(count($changedfieldsarray) > 0) { $fieldnames = implode(", ", $changedfieldsarray); $this->warning(sprintf(__("Following fields have been changed: %s"), $fieldnames )); } }); It uses the uncache method to compare stored values from the DB and the new ones entered in the form. This informs the editor only once directly after form submission. If the editor push the save button once more and nothing was changed, the message will not be shown again. This is the main difference between this and the previous method. Attention: This method uncaches the page and therefore all entered values will be cleared after pressing the submit button and no sucessfull saving of the page - so use this method with care.
-
Another idea would be to use https://github.com/sunra/php-simple-html-dom-parser library, works like Jquery, but its only PHP and run server side. You can manipulate the output of fe comments->render function and you can add classes to it.
- 5 replies
-
- 1
-
- styling
- comments module
-
(and 2 more)
Tagged with:
-
Another approach would be to add the CSS classes with Jquery onload, but you are also not aware of changes in the future. I use the first method for years now and I had no problems. I dont think that there will be major changes taken in the future. At the moment you could only change some attributes of the form tag, but not for the inputs.
- 5 replies
-
- 1
-
- styling
- comments module
-
(and 2 more)
Tagged with:
-
Take a look at this post (https://processwire.com/talk/topic/17263-custom-comments-form-and-list-styling/?do=findComment&comment=151627): You can copy the comment files from wire/modules into the module folder of your site folder (site/modules) and there you can change your CSS classes and the markup too. I think this is the best approach to adapt the comments output to your needs. You dont need to hack anything and it will not be overwritten during updates.
- 5 replies
-
- 1
-
- styling
- comments module
-
(and 2 more)
Tagged with:
-
Hello, I want to reset the tracked changes on the edited page if a checkbox is checked. But unfortunately the changes are still there. Here is what I have so far: $pages->addHookBefore('saveReady', function($event) { $page = $event->arguments[0]; if($page->createevents == true) { $page->resetTrackChanges(); } }); So its a simple hook that runs before the page is saved. If the checkbox called "createevents" is checked, then the tracked changes should be reset. But this doesnt work. I was looking at http://cheatsheet.processwire.com/pagearray-wirearray/change-tracking/a-resettrackchanges/ and also at this post from Ryan (https://processwire.com/talk/topic/4880-questions-about-the-usage-of-trackchanges/?do=findComment&comment=47670) but I dont know why it is not working. Only to mention: I use the latest dev and PHP 7 Maybe someone can help me out?
-
Sometimes you need to track changes in certain values of a page to take an action afterwards. In this example I will show you how to show a simple message after changes to inform the user that field values have been changed. Put this piece of code inside your ready.php. //Track changes $pages->addHookAfter('saveReady', function($event) { $page = $event->arguments[0]; if(!in_array($page->template->name, array('template1','template2'))) return; $fields = array('field1','field2','field3','field4'); $changedfieldsarray = array(); foreach($fields as $field) { if ($page->isChanged($field)) { $changedfieldsarray[] = $page->fields->get($field, true)->label; } } $fieldnames = implode(", ", $changedfieldsarray); $this->warning(sprintf(__("Following fields have been changed: %s"), $fieldnames )); }); The first restriction in this example is to run this hook "aftersaveReady" and only on certain templates: in this case template1 and template 2. You need to rename this to your template names. Remove the following line of code if you want it to run on all pages (no restrictions): if(!in_array($page->template->name, array('template1','template2'))) return; Now you have to define the fields where you want to track changes (take a look at this line): $fields = array('field1','field2','field3','field4'); In this case the fields are called "field1 to field4". Rename it to your field names. The API call to track changes is "$page->isChanged('fieldname')". You will find more information at https://processwire.com/api/ref/page/is-changed/. Use a foreach to loop through the fields array and store all changed fields inside an array. In the last step all the changed fields were outputted inside a message to inform the user. In this case I want to show the labels instead of the field names. Only to mention: The changes will keep alive, so you have to delete it manually (http://cheatsheet.processwire.com/pagearray-wirearray/change-tracking/a-resettrackchanges/). This little tutorial should only be a starting point for your own coding.
-
Hello, this is an issue I was struggeling for a while to find a working solution: The goal: A page must contain at least 1 child page. If there are more child pages than prevent the editor (user) from deleting the last child page and output a message that the deletion of the last page is not allowed. Idea behind this: I have pages which holds all the information of events, but the date or dates of the event are all located in child pages: - event page - event date 1 - eventdate 2... and so on. Each event must have at least on date. An event with no date doesnt make sense. This was the reason to not allow the deletion of the last date. Here is the code that you should copy into your ready.php $wire->addHookBefore("Pages::trash", function($event) { $page = $event->arguments(0); if(!in_array($page->template->name, array('single-date', 'single-event', 'single-business-vacation', 'single-special-business-hours'))) return; $parent = $page->parent; $childrennumber = count($page->parent->children); if($childrennumber === 1) { $event->replace = true; // now original function won't be called $event->return = $this->warning("Trashing not allowed!"); } else { $this->message("1 Page was deleted"); } }); 1) You must hook before the page will put to trash so "addHookBefore" has to be used 2) If you want to restrict it to certain types of templates than put the names of the templates in an array (in this case the templates I want to run the hook are "single-date, single-event, single-business-vacation or single-special-business-hour". If you want it to run on all pages simply remove this line from the code: if(!in_array($page->template->name, array('single-date', 'single-event', 'single-business-vacation', 'single-special-business-hours'))) return; 3) You need to get the number of all child pages from the parent to check if it is the last child or not. If there are more than 1 page and you delete on of them you get the message "1 page deleted" - so everthing is ok and the deletion of the page take place 4) If it is the last child than the trash function will be replaced by a message. So the trash function will not be executed and the warning message will be displayed instead. 5) Inform the editor with this message that the deletion of the last child is not allowed. I use here the message type "warning" (color orange), but you can also use "error" or "message" Thats all - hope this is useful for others that need something similar Only to mention: This works also via Ajax deletion fe in the page tree, but in first instance it seems that the last child was deleted because it disappears, but after refreshing the page the last child will be visible again.
-
Hook to change page status depending on children
Juergen replied to Juergen's topic in General Support
Here is the final code the prevents the deletion of the last child: I restrict it that the child is type of one of the following templates: single-date, single-event, single-business-vacation or single-special-business-hours. //Prevent deletion of the the last child $wire->addHookBefore("Pages::trash", function($event) { $page = $event->arguments(0); if(!in_array($page->template->name, array('single-date', 'single-event', 'single-business-vacation', 'single-special-business-hours'))) return; $parent = $page->parent; $childrennumber = count($page->parent->children); if($childrennumber === 1) { $event->replace = true; // now original function won't be called $event->return = $this->message("Trashing not allowed! There must be at least 1 page."); } }); I put a complete description in the Tutorial section -
Hook to change page status depending on children
Juergen replied to Juergen's topic in General Support
Ok, I have found a solution to prevent the deletion of a page: $wire->addHookBefore("Pages::trash", function($event) { $page = $event->object; $event->replace = true; // now original function won't be called $event->return = $this->message("Trashing not allowed!"); }); So it must be adapted to only run on certain templates and if there is only 1 child. -
Hook to change page status depending on children
Juergen replied to Juergen's topic in General Support
An idea would be to check the number of children before the deletion. If there is only 1 child than prevent processing of the delete function. Maybe lets say a hook that prevents the execution of the deletion???? Something like $event->replace = true; -
Hello @ all, I have the following scenario: A parent page status should be changed depending on the number of children. If there is at least 1 child the status should be published, if there are no children the statuts should be unpublished. Seems easy to realize at first sight, but ... the button of the parent page should also change. If there are children (at least 1): Only the save button should be displayed. If there are no children: The 2 buttons should be displayed. The children will be created or deleted via a Pagetable field and can be also created by clicking a checkbox in the parent page. I have tried to hook into "added" and "deleted" and also "trashed" to set the page->parent->status and it seems to work, but the button appearence will not change. So the status of the parent page seems to be changed but not the buttons (that is the problem) . Here is what it looks like after deleting of the last child: As you can see the status of the page was changed to "2048" which is unpublished, but the button is the same as before (no change). If you take a look into the settings tab you will see that the checkbox for unpublish is also not checked: The buttons change only if I hook into "before save ready" but this kind of hook doesnt take care of added or delete pages. It is also not possible to check for hasChildren because the creation of the children take place after saving of the parent page. Does someone has struggled with the same problem and has a working solution? Another approach would be to prevent the deletion of the last child.
-
Hello @ all, It want to change the markup of the notices (error, warning, message) a little bit. By default error messages in the admin look like this: There is the hint that a field is required and next to this message is the name of the field in parenthesis. This is the point, where I like to hook into. I want to replace the name of the field by the field label because editors dont know what the name of the field is. So if the user is not superuser this hook should take place. It is not a thing that is very important to me, but if there is a render function of the messages that will be hookable, it would be great if someone can tell me about. I have taken a look at https://processwire.com/api/hooks/captain-hook/ but I cannot find anything so maybe it will not be possible. But who knows....
-
I am using it too and I have not detected any problems since then.
-
Problem with field validation and values added via saveReady hook
Juergen replied to Juergen's topic in General Support
No need to investigate further. I have disabled the validation if the value will be added via a hook. The validation only take place if the value is entered manually -
Hello @ all, I cannot find a solution for this behavior: I want to validate a field which value is sometimes filled out manually and sometimes via a hook. The custom validation was done with this type of hook: $pages->addHookAfter("InputfieldDatetime::processInput", function($event) { The hook for adding a value in this field is done via this type of hook: $pages->addHookBefore('saveReady', function($event){ The 2 hooks work but the problem is that "processInput" runs before "saveReady" and so I always get the error that the field is empty. But the value will be added correctly if you can see at the following screenshot. If I fill out the value manually everything works. So which type of hook runs before "processinput" and can be used to populate a field with a value. Thanks
-
I know, this is the solution if you have only 1 template assigned.
-
How to store translateable value in multilanguage textfield via API
Juergen replied to Juergen's topic in General Support
My final solution is to use a Hook as @LostKobrakai recommended: Here is an example for others to hook into the page tree label. Code has to be placed inside ready.php $wire->addHookAfter('ProcessPageListRender::getPageLabel', function($event) { $label = $event->object; $page = $event->arguments(0); if($page->template->name == "single-date"){ $event->return = $page->title.'-test'; } }); For testing purposes I only use it on one template type called "single-date" and I change the label from "title" to "title + test". Here is what it looks like: As you can see the text "test" will be added on that template type next to the page title. This is only for others to see how it can be done. You have the idea. Only to mention: You will only need this Hook if you want to add text or values which are not stored in the DB. Otherwise you can use the field in the template settings. -
If you want to add your own button value at the add button of a pagetable field, you only have to put this little piece of code inside your ready.php file. $wire->addHookBefore('InputfieldPageTable::render', function($event) { $table = $event->object; if(!in_array($table->name, array('datespagetable'))) return; $this->addHookBefore("InputfieldButton::render", null, function(HookEvent $event){ $button = $event->object; if($button->name == 'button'){ $button->attr('value', 'Test'); } }); }); In this case I limit it to a certain pagetable field called "datespagetable". You have to change it to the name of your desired pagetable field. If you want to change it for all pagetable fields (no restrictions) simply remove the following line from the code: if(!in_array($table->name, array('datespagetable'))) return; If you want to add it to more than 1 pagetable field, then write all the fieldnames into the array: if(!in_array($table->name, array('datespagetable','pagetable1','pagetable2'))) return; You can change the value of the button text to your needs in this line of code: $button->attr('value', 'Test'); I simply called it "Test" in this case to show how it is working. If you need it to be a translateable string simply use: $button->attr('value', __('Test')); And now this is the result: This let you customize your pagetable field a little bit. Fe you can use "Add News" or "Add new events" or something else. If you want to change another attribute than the value please take a look at the following page: https://github.com/processwire/processwire/blob/master/wire/modules/Inputfield/InputfieldButton.module Best regards