Elementor Widget Post Settings

User
add setting field for add number of post and order by elementor widget
Assistant
To add custom settings for "Number of Posts" and "Order By" to an Elementor widget, you can extend the widget's controls in its PHP class. Here's how you can do it:

### Steps:

1. **Locate Your Custom Widget Class**
If you've already created a custom Elementor widget, open its PHP file.

2. **Add Controls for Number of Posts and Order By**
Use the `add_control` method to include these options in your widget.

Here’s a sample code snippet:

protected function _register_controls() {
    $this->start_controls_section(
        'content_section',
        [
            'label' => __( 'Content', 'your-text-domain' ),
            'tab' => ElementorControls_Manager::TAB_CONTENT,
        ]
    );

    // Number of Posts Control
    $this->add_control(
        'number_of_posts',
        [
            'label' => __( 'Number of Posts', 'your-text-domain' ),
            'type' => ElementorControls_Manager::NUMBER,
            'default' => 5,
            'description' => __( 'Enter the number of posts to display.', 'your-text-domain' ),
        ]
    );

    // Order By Control
    $this->add_control(
        'order_by',
        [
            'label' => __( 'Order By', 'your-text-domain' ),
            'type' => ElementorControls_Manager::SELECT,
            'default' => 'date',
            'options' => [
                'date' => __( 'Date', 'your-text-domain' ),
                'title' => __( 'Title', 'your-text-domain' ),
                'rand' => __( 'Random', 'your-text-domain' ),
                'ID' => __( 'ID', 'your-text-domain' ),
            ],
            'description' => __( 'Select the order for displaying posts.', 'your-text-domain' ),
        ]
    );

    $this->end_controls_section();
}

3. **Fetch Posts in the Widget Render Method**
Use these settings to query posts in the `render()` method.

protected function render() {
    $settings = $this->get_settings_for_display();

    $args = [
        'post_type' => 'post',
        'posts_per_page' => $settings['number_of_posts'],
        'orderby' => $settings['order_by'],
    ];

    $query = new WP_Query($args);

    if ($query->have_posts()) {
        echo '<div class="custom-posts-list">';
        while ($query->have_posts()) {
            $query->the_post();
            echo '<div class="post-item">';
            echo '<h2><a href="' . get_permalink() . '">' . get_the_title() . '</a></h2>';
            echo '</div>';
        }
        echo '</div>';
    }

    wp_reset_postdata();
}

4. **Test the Widget**
– Add the widget in Elementor and verify that the fields appear in the settings panel.
– Ensure the "Number of Posts" and "Order By" options work as expected.

5. **Optional Enhancements**
– Add a control for selecting post types if you want to extend functionality.
– Include validation for input fields if needed.

Let me know if you need help with testing or enhancing this!

User
also add option for desc/asc and set default to date and number of post to 2
Assistant
Here's the updated code that includes an option for **ascending/descending order**, with defaults set to **"date"** for the `order_by` field and **2** for the `number_of_posts` field.

### Updated Code:

protected function _register_controls() {
    $this->start_controls_section(
        'content_section',
        [
            'label' => __( 'Content', 'your-text-domain' ),
            'tab' => ElementorControls_Manager::TAB_CONTENT,
        ]
    );

    // Number of Posts Control
    $this->add_control(
        'number_of_posts',
        [
            'label' => __( 'Number of Posts', 'your-text-domain' ),
            'type' => ElementorControls_Manager::NUMBER,
            'default' => 2, // Default number of posts
            'description' => __( 'Enter the number of posts to display.', 'your-text-domain' ),
        ]
    );

    // Order By Control
    $this->add_control(
        'order_by',
        [
            'label' => __( 'Order By', 'your-text-domain' ),
            'type' => ElementorControls_Manager::SELECT,
            'default' => 'date', // Default ordering
            'options' => [
                'date' => __( 'Date', 'your-text-domain' ),
                'title' => __( 'Title', 'your-text-domain' ),
                'rand' => __( 'Random', 'your-text-domain' ),
                'ID' => __( 'ID', 'your-text-domain' ),
            ],
            'description' => __( 'Select the field to order posts by.', 'your-text-domain' ),
        ]
    );

    // Order Control (Ascending/Descending)
    $this->add_control(
        'order',
        [
            'label' => __( 'Order', 'your-text-domain' ),
            'type' => ElementorControls_Manager::SELECT,
            'default' => 'DESC', // Default order
            'options' => [
                'ASC' => __( 'Ascending', 'your-text-domain' ),
                'DESC' => __( 'Descending', 'your-text-domain' ),
            ],
            'description' => __( 'Select the order direction.', 'your-text-domain' ),
        ]
    );

    $this->end_controls_section();
}

### Update the `render()` Method

Adjust the `render()` method to incorporate the new `order` option:

protected function render() {
    $settings = $this->get_settings_for_display();

    $args = [
        'post_type' => 'post',
        'posts_per_page' => $settings['number_of_posts'], // Number of posts to display
        'orderby' => $settings['order_by'], // Field to order by
        'order' => $settings['order'], // ASC or DESC
    ];

    $query = new WP_Query($args);

    if ($query->have_posts()) {
        echo '<div class="custom-posts-list">';
        while ($query->have_posts()) {
            $query->the_post();
            echo '<div class="post-item">';
            echo '<h2><a href="' . get_permalink() . '">' . get_the_title() . '</a></h2>';
            echo '</div>';
        }
        echo '</div>';
    }

    wp_reset_postdata();
}

### Summary of Changes:
1. **Default Values:**
– `number_of_posts`: Default is set to `2`.
– `order_by`: Default is set to `date`.
– `order`: Default is set to `DESC`.

2. **New Control:**
– `order`: Added to allow "Ascending" or "Descending" order.

3. **Query Adjustments:**
– The query now includes the `order` parameter.

### Testing:
– Add your widget to a page in Elementor.
– Adjust the "Number of Posts," "Order By," and "Order" settings to test different configurations.

Let me know if you need additional functionality!

User
$settings['number_of_posts'] ?? 3 check if is_numeric and greater than 0
Assistant
To ensure that `$settings['number_of_posts']` is both numeric and greater than 0, you can add a validation check in the `render()` method. If it fails the validation, default it to `3`.

Here’s the updated `render()` method with the validation:

### Updated `render()` Method:

protected function render() {
    $settings = $this->get_settings_for_display();

    // Validate number of posts
    $number_of_posts = isset($settings['number_of_posts']) && is_numeric($settings['number_of_posts']) && $settings['number_of_posts'] > 0
        ? intval($settings['number_of_posts'])
        : 3; // Default to 3 if validation fails

    $args = [
        'post_type' => 'post',
        'posts_per_page' => $number_of_posts, // Number of posts to display
        'orderby' => $settings['order_by'] ?? 'date', // Default to 'date' if not set
        'order' => $settings['order'] ?? 'DESC', // Default to 'DESC' if not set
    ];

    $query = new WP_Query($args);

    if ($query->have_posts()) {
        echo '<div class="custom-posts-list">';
        while ($query->have_posts()) {
            $query->the_post();
            echo '<div class="post-item">';
            echo '<h2><a href="' . get_permalink() . '">' . get_the_title() . '</a></h2>';
            echo '</div>';
        }
        echo '</div>';
    }

    wp_reset_postdata();
}

### Explanation of Changes:
1. **Validation for `number_of_posts`:**
– Checks if the field exists, is numeric, and greater than 0.
– Defaults to `3` if validation fails.

2. **Fallback for `order_by` and `order`:**
– `order_by`: Defaults to `'date'` if not set.
– `order`: Defaults to `'DESC'` if not set.

### Summary:
– If the user enters an invalid value for the "Number of Posts" field (e.g., negative numbers, non-numeric values), the widget will gracefully fall back to displaying 3 posts.
– The `order_by` and `order` fields also have default values to prevent errors.

This approach ensures that your widget is robust and handles invalid user input correctly. Let me know if you need further assistance!

User
jQuery(document).ready(function ($) {
$('.project-taxonomy-filter').on('change', function () {
let filters = {};

// Loop through all dropdowns to collect data
$('.project-taxonomy-filter').each(function () {
const taxonomy = $(this).data('taxonomy');
const slug = $(this).val();

if (slug) {
filters[taxonomy] = slug;
}
});

$.ajax({
url: solaron_ajax.ajax_url,
type: 'POST',
data: {
action: 'filter_project_posts',
filters: filters,
},
beforeSend: function () {
$('#ajax-project-content').html('Loading…');
},
success: function (response) {
$('#ajax-project-content').html(response);
},
});
});
});
apply above if project-taxonomy-filter class exist on that page

Assistant
To ensure that the jQuery script is applied only if the `.project-taxonomy-filter` class exists on the page, you can include a conditional check before attaching the `change` event handler. Here's the updated script:

### Updated Script:

jQuery(document).ready(function ($) {
    // Check if elements with the class 'project-taxonomy-filter' exist
    if ($('.project-taxonomy-filter').length > 0) {
        $('.project-taxonomy-filter').on('change', function () {
            let filters = {};

            // Loop through all dropdowns to collect data
            $('.project-taxonomy-filter').each(function () {
                const taxonomy = $(this).data('taxonomy');
                const slug = $(this).val();

                if (slug) {
                    filters[taxonomy] = slug;
                }
            });

            $.ajax({
                url: solaron_ajax.ajax_url,
                type: 'POST',
                data: {
                    action: 'filter_project_posts',
                    filters: filters,
                },
                beforeSend: function () {
                    $('#ajax-project-content').html('<p>Loading...</p>');
                },
                success: function (response) {
                    $('#ajax-project-content').html(response);
                },
            });
        });
    }
});

### Explanation of Changes:
1. **Existence Check:**
Before binding the event handler, the script checks if any elements with the `.project-taxonomy-filter` class exist using `if ($('.project-taxonomy-filter').length > 0)`.

2. **Prevents Unnecessary Binding:**
If the class is not present, the script does nothing, improving performance and avoiding errors.

### Additional Notes:
– Ensure that the `solaron_ajax.ajax_url` variable is correctly localized in your WordPress setup using `wp_localize_script`.
– Verify that the `#ajax-project-content` element is present on the page where you expect the content to be updated.

This approach ensures the script runs only when the required elements are present on the page. Let me know if you need further adjustments!

Leave a Comment

Your email address will not be published. Required fields are marked *