- This topic has 6 replies, 2 voices, and was last updated 2 years, 6 months ago by
Steve.
-
AuthorPosts
-
-
July 24, 2019 at 6:04 pm #9463
joezimParticipantHere’s my old version of a settings page:
<?php /* Setting: reciprocity_changelog Order: 1 */ $states = \App\Model\ReciprocityStates::getStates(); piklist('field', array( 'type' => 'group', 'field' => 'changes', 'label' => 'Updates', 'list' => false, 'description' => 'A grouped field with the field parameter set.', 'add_more' => true, 'fields' => array( array( 'type' => 'date', 'field' => 'date', 'label' => 'Date', 'columns' => 2 ), array( 'type' => 'select', 'field' => 'state', 'label' => 'State', 'columns' => 4, 'choices' => array_combine($states, $states) ), array( 'type' => 'text', 'field' => 'description', 'label' => 'Description', 'columns' => 6 ) ) ));It simply has a repeater for 3 fields. The problem is that there are 826 (and growing) items in that array, so the page takes around a minute to run the JS and convert the fields to repeater rows, etc. So I decide to manually build the form to be simpler, like this:
<?php /* Setting: reciprocity_changelog Order: 1 */ $states = \App\Model\ReciprocityStates::getStates(); $updates = \App\Model\ReciprocityData::getReciprocityUpdates(); ?> <div class="new_log"> <p>Fill out the fields below and click "Add" to add a new update.</p> <div class="field-row"> <label class="field"> <span class="field-label">Date</span> <input type="date" name="reciprocity_changelog[changes][<?= count($updates) ?>][date]" class="field-input"> </label> <label class="field"> <span class="field-label">State</span> <select name="reciprocity_changelog[changes][<?= count($updates) ?>][state]" class="field-input"> <option value="">Select a State</option> <?php foreach ($states as $state) : ?> <option value="<?= $state ?>"><?= $state ?></option> <?php endforeach ?> </select> </label> <label class="field field--wide"> <span class="field-label">Description</span> <input type="text" name="reciprocity_changelog[changes][<?= count($updates) ?>][description]" class="field-input description-field"> </label> </div> <button type="submit" name="submit" id="submit" class="button button-primary">Add</button> </div> <?php foreach ($updates as $i => $update) : ?> <?php if ($i < 10) : // Only make the latest 10 editable ?> <div class="field-row"> <label class="field"> <span class="field-label">Date</span> <input type="date" name="reciprocity_changelog[changes][<?= $i ?>][date]" value="<?= $update['date'] ?>" class="field-input"> </label> <label class="field"> <span class="field-label">State</span> <select name="reciprocity_changelog[changes][<?= $i ?>][state]" class="field-input"> <?php foreach ($states as $state) : ?> <option value="<?= $state ?>" <?= $state == $update['state'] ? 'selected' : '' ?>><?= $state ?></option> <?php endforeach ?> </select> </label> <label class="field field--wide"> <span class="field-label">Description</span> <input type="text" name="reciprocity_changelog[changes][<?= $i ?>][description]" value="<?= $update['description'] ?>" class="field-input description-field"> </label> </div> <?php else : ?> <input type="hidden" name="reciprocity_changelog[changes][<?= $i ?>][date]" value="<?= $update['date'] ?>"> <input type="hidden" name="reciprocity_changelog[changes][<?= $i ?>][state]" value="<?= $update['state'] ?>"> <input type="hidden" name="reciprocity_changelog[changes][<?= $i ?>][description]" value="<?= $update['description'] ?>"> <?php endif ?> <?php endforeach ?> ?>I’m pulling in the data and building the form fields manually. Only the first 10 are visible and editable, the rest are hidden fields to make the page more performant (note, when I call
getReciprocityUpdatesit orders the updates by date, so it will always have the latest 10 on top). There’s also a set of fields at the top to append another row at the end of the array (note the [count($updates)] to add the index number in the field name). The field names are exactly the same, as far as I can tell, as the ones generated by piklist in the original version, but when I click the submit button the data doesn’t update. It says “Settings Saved” at the top, but no change was made to the DB. What am I missing? -
July 25, 2019 at 3:31 pm #9467
joezimParticipantNevermind. I figured it out (I believe. I haven’t actually finished fixing it and testing to see it work). Turns out it wasn’t working with the Piklist version either. With so many entries, I was running up against the POST request size limit for my server, so the data was getting truncated. The truncation was causing it to fail validation so Piklist was saying to use the old value.
-
July 25, 2019 at 3:43 pm #9468
SteveKeymasterYou may also run into a rendering issue with the browser. We’ve seen that happen.
800+ repeater fields is probably not the best user experience. Some suggestions:
1) Break them up under different Workflow tabs:
https://piklist.github.io/docs/tutorials/workflows/building-first-workflow/2) Use a Post Type instead, and have 800+ posts.
Good luck!
-
July 25, 2019 at 5:04 pm #9469
joezimParticipantYeah, I’m breaking them up. There are 52 “tabs” because they are broken up for each of the 50 US States plus Washington DC and New York City, so literal tabs don’t make sense because there would be so many, and *workflow* tabs *really* don’t make any sense for this. I considered a post type, but each entry only has 3 tiny bits of info, so it doesn’t make much sense to bring in the complexities of a custom post type. I’m going to have a “Main” page with a link to each of the 52 “states” and just list out all of them for that state to be editable and have a box at the top of the page for adding a new entry. It’ll be a lot simpler and it should be many years before we run into any types of size limitations.
Thanks.
-
July 26, 2019 at 10:01 am #9470
SteveKeymasterI’d love to see it. Send over screenshots if you can.
Steve
-
July 29, 2019 at 10:30 am #9473
joezimParticipantSplit the states up:
https://screencast.com/t/fWIZ5oDqNZEach state:
https://screencast.com/t/VIvtKErBiHere’s the code under
piklist/parts/settings/changelog.php<?php /* Setting: reciprocity_changelog Order: 1 */ use \App\Model\ReciprocityData; use \App\Model\ReciprocityStates; $selectedState = $_GET['state']; $states = ReciprocityStates::getStates(); /** * SECTION 1: CHOOSE A STATE */ if (!$selectedState || empty($selectedState)): ?> <h1>Choose A State</h1> <div class="state-selector"> <?php foreach ($states as $state): ?> <?php $stateAbbreviation = ReciprocityStates::getLowercaseStateAbbreviation($state);?> <a href="<?=admin_url('edit.php?post_type=reciprocity-pages&page=changelog&state=' . $stateAbbreviation)?>" class="state-selector__option"><?=$state?></a> <?php endforeach?> </div> <style> .state-selector { columns: 4; } .state-selector__option { display: block; font-size: 1.5em; line-height: 2; } #submit { display: none; } </style> <?php /** * SECTION 2: STATE IS CHOSEN SO SHOW UPDATES */ else: $selectedStateName = ReciprocityStates::getStateNameFromAbbreviation($selectedState); $updates = ReciprocityData::getReciprocityUpdates($selectedStateName); ?> <h1><?=$selectedStateName?> Changelog</h1> <p class="changelog-note">Changelog descriptions allow Markdown, which allow links in the following format:<br><code>Read the [blog post](https://www.usconcealedcarry.com/link-to-blog-post).</code></p> <div class="new_log"> <p>Fill out the fields below and click "Add Update" to add a new update.</p> <div class="field-row"> <label class="field"> <span class="field-label">Date</span> <input type="date" name="reciprocity_changelog[<?=$selectedStateName?>][<?=count($updates)?>][date]" class="field-input"> </label> <label class="field field--wide"> <span class="field-label">Description</span> <input type="text" name="reciprocity_changelog[<?=$selectedStateName?>][<?=count($updates)?>][description]" class="field-input description-field"> </label> </div> <button type="submit" name="submit" id="submit" class="button button-primary">Add Update</button> </div> <?php foreach ($updates as $i => $update): ?> <div class="field-row"> <label class="field"> <span class="field-label">Date</span> <input type="date" name="reciprocity_changelog[<?=$selectedStateName?>][<?=$i?>][date]" value="<?=$update['date']?>" class="field-input"> </label> <label class="field field--wide"> <span class="field-label">Description</span> <input type="text" name="reciprocity_changelog[<?=$selectedStateName?>][<?=$i?>][description]" value="<?=$update['description']?>" class="field-input description-field"> </label> </div> <?php endforeach?> <style> .changelog-note { background: #def; border: 1px solid #69b; border-radius: 5px; padding: 15px; } .new_log { background: #fafafa; border: 1px solid #ddd; border-radius: 5px; padding: 15px; margin: 15px 0; } .field-row { font-size: 16px; display: flex; padding-bottom: 15px; } .field { flex: 1; padding-right: 15px; } .field:last-child { padding-right: 0; } .field--wide { flex-grow: 5; } .field-label { font-weight: bold; display: block; padding-bottom: 5px; padding-left: 5px; } .field-input { font-size: inherit; height: 2em !important; padding-left: 10px !important; padding-right: 10px !important; width: 100%; line-height: inherit !important; } .description-field { min-width: 500px; } </style> <?php endif?> <!-- STYLES FOR BOTH SECTIONS --> <style> #wpbody-content h2 { display: none; } </style>And the
pre_update_option_xxfilter:function changelogUpdateFilter($new, $old) { // Remove Piklist's default filter. It doesn't work for our needs. remove_filter('pre_update_option_reciprocity_changelog', array('piklist_setting', 'pre_update_option'), 10); $returnVal = $old; foreach ($new as $state => $updates) { // Filter out "Empty" results (submitted form without adding a new entry) $updates = array_filter($updates, function ($update) { return !empty($update['date']) && !empty($update['description']); }); // Make sure the updates are in new->old order usort($updates, function ($a, $b) { $a = $a['date']; $b = $b['date']; if ($a == $b) { return 0; } return ($a > $b) ? -1 : 1; }); // Add new entries to the rest of the changelog by replacing all of the state's update with what was submitted, // since previous updates to that state are included in the form submission. $returnVal[$state] = $updates; } return $returnVal; } -
July 29, 2019 at 4:17 pm #9474
SteveKeymasterThat is a very cool way to solve that issue. A real creative use of Piklist. Good job!
-
-
AuthorPosts
- The topic ‘Manual Form Fields for Settings Page’ is closed to new replies.