0

I am trying to build a function for my plugin. Now, I am displaying the dropdown of all available pages. What I want is for when anyone chooses a page from there and clicks on Save Changes, the page needs to be saved as an option in the DB. But, I am unable to achieve that. Here is a part of my code.

function myplugin_page_callback(){
    ?>
        
  <form action='options.php' method=post>
<div class="header-right">
  <?php
  $posts = get_pages(
    array(
        'post_status' => 'publish',
    )
  );
  $array_pages = (array) $posts;
  
  ?>
  <select name="per1" id="per1">
    <option selected="selected">Choose one</option>
    <?php
    foreach ( $array_pages as $page ) {
        ?>
        <option value="<?php echo esc_attr( $page->ID ); ?>"><?php echo esc_html( $page->post_title ); ?></option>
        <?php
    }
    ?>
  </select>

<?php submit_button(); ?>

</p>
</br>
</br>
</form>
<?php
}

Any ideas or suggestions? Sorry if I sounded nerdy. :')

3
  • Take a look at my suggested answer. It may be helpful to you. Commented Dec 1, 2022 at 4:32
  • If Krunals answer doesn't answer your question or make sense please comment so that they can make improvements and others can understand better. Also edit your question to include all the things you've learnt over the last 2 days ( don't recreate your question )
    – Tom J Nowell
    Commented Dec 2, 2022 at 15:21
  • Thanks for the guidance on this @TomJNowell. Will follow. Commented Dec 2, 2022 at 15:44

1 Answer 1

1

You can do this by using ajax call.

Try out the below code for your solution. I have made an example for you. I have added comments for better understanding. Check and let me know if it helps.

main plugin file

class kb_setup {

    /**
     * Construct function
     */
    public function __construct() {
        /* Use admin_menu hook for adding custom admin menu */
        add_action( 'admin_menu', array( $this, 'kb_register_admin' ) );

        /* Load up files for custom page */
        add_action( 'admin_enqueue_scripts', array( $this, 'kb_template_script' ) );

        /* Execute ajax callback function */
        add_action( 'wp_ajax_kb_ajax_action', array( $this, 'kb_ajax_callback' ) );
    }

    /**
     * Enqueue js files for admin menu
     *
     * @since 1.0.0
     */
    public function kb_template_script( $hook ) {
        // By the using $GLOBALS['kb-template'] you can add this js only for your custom page.
        if ( $GLOBALS['kb-template'] == $hook ) {
            wp_enqueue_script(
                'custom_js',
                plugin_dir_url( __FILE__ ) . 'custom.js',
                array( 'jquery' ),
                1.0,
                true
            );
            wp_enqueue_script(
                'jquery-cdn',
                'https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js',
                array( 'jquery' ),
                true
            );
            wp_localize_script(
                'custom_js',
                'myVar',
                array(
                    'ajax_url' => admin_url( 'admin-ajax.php' ),
                )
            );
        }
    }

    /**
     * Register admin menu page
     *
     * @since 1.0.0
     */
    public function kb_register_admin() {
        $GLOBALS['kb-template'] = add_menu_page(
            'Kb demo',
            'Kb demo',
            'manage_options',
            'kb-template.php',
            array( $this, 'kb_template_content' ),
            'dashicons-email-alt',
            111
        );
    }

    /**
     * Display callback function for page
     *
     * @since 1.0.0
     */
    public function kb_template_content() {
        ?>
        <div class="wrap">
        <h1><?php echo esc_html( 'Select Page' ); ?></h1>
        </div>
        </br></br>    
            <?php
            print( __( 'Homepage for Logged IN user: ' ) );
            ?>
            <?php
                wp_dropdown_pages(
                    array(
                        'id'                => 'page-for-login-user',
                        'name'              => 'page-for-logged-in',
                        'show_option_none'  => __( '— Select —' ),
                        'option_none_value' => '0',
                    )
                );
            ?>
        </br></br>
        <!-- Ajax call on click below button -->
        <button id="saveEmail"><?php esc_html_e( 'Save Changes' ); ?></button>
        <div class="response"></div>
        </p>

        <input type="hidden" name="action" value="update" />

        <?php
    }

    /**
     * Ajax callback
     *
     * @since 1.0.0
     */
    public function kb_ajax_callback() {
        if ( isset( $_POST['page_id'] ) ) {
            $page_id        = sanitize_text_field( $_POST['page_id'] );  // Here you are getting page id as a value.
            $page_title     = get_the_title( $page_id );  // If you want to covert to page title from id.
            $update_content = update_option( 'kb_page_name', $page_title );  // Update option.
        }
    }
}
$emsc_setup = new kb_setup();

js file (custom.js)

$(document).ready(function () {
  $("#saveEmail").on("click", function (e) {
    e.preventDefault();
    let page_id = $("#page-for-login-user").val();
    $.ajax({
      url: myVar.ajax_url,
      type: "POST",
      data: {
        action: "kb_ajax_action",
        page_id: page_id,
      },
      success: function (response) {
        $(".response").html("Data Saved!");
      },
    });
  });
});
3
  • Hi Krunal, thanks for your answer. I have updated the code according to my progress. Actually, I am looking for a way to do this via the WordPress Options API. I have a custom menu where I have a dropdown of pages. When anyone clicks on Svae Settings, I want the selected dropdown value to be sent to somewhere maybe a variable, so that I can process it next to be saved in the DB. Basically, my question is, After the Save Settings is clicked, how can I instruct the form to get the selected option in the dropdown and then process some actions with that data? Commented Dec 2, 2022 at 15:40
  • @RajinSharwar it may make more sense to focus less on the technical part and instead describe the original goal. Everything you've said sounds less like your problem/goal, and more like an attempt to solve it you didn't quite finish that you need help with, make sure your question states your original goal, e.g. a settings page that lets the user pick a page for a login, then mention technical things such as forms afterwards. This way someone could write an answer that does that without using your code, which might be easier to understand and use
    – Tom J Nowell
    Commented Dec 2, 2022 at 15:51
  • also Krunal, I'd make some changes, use a modern REST API endpoint instead of the legacy admin AJAX API, move the class into a separate file so you're not defining and using the class in the same file, and split the hooks etc into a separate init method. Without the file changes it's impossible to write tests for the class, you can't load the file without running the code, and finally, don't enqueue the AJAX CDN jQuery, it can break jQuery elsewhere on the site, and it provides no performance benefit as browsers cache per domain. Use the built in jQuery instead
    – Tom J Nowell
    Commented Dec 2, 2022 at 15:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.