# Shared To-Do List Widget

> Adds a team to-do list to the dashboard where editors can add tasks, tick them off and clear finished ones, shared by everyone who can edit content.

- Type: PHP
- Runs: Admin only
- Category: [Dashboard](https://wpide.com/library/category/dashboard/)
- Tags: dashboard-widget, tasks, team
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/dash-shared-todo-widget/

## Code

```php
add_action( 'wp_dashboard_setup', function () {
    if ( ! current_user_can( 'edit_others_posts' ) ) {
        return;
    }

    wp_add_dashboard_widget( 'wpide_todo', 'Team to-do list', function () {
        $items = (array) get_option( 'wpide_todo_items', array() );
        ?>
        <ul id="wpide-todo-list" style="margin-top:0">
            <?php foreach ( $items as $i => $item ) : ?>
                <li><label><input type="checkbox" data-index="<?php echo (int) $i; ?>" <?php checked( ! empty( $item['done'] ) ); ?>>
                    <span style="<?php echo ! empty( $item['done'] ) ? 'text-decoration:line-through;color:#787c82' : ''; ?>"><?php echo esc_html( $item['text'] ); ?></span></label></li>
            <?php endforeach; ?>
            <?php if ( ! $items ) : ?><li><em>Nothing to do.</em></li><?php endif; ?>
        </ul>
        <form id="wpide-todo-form" style="display:flex;gap:6px">
            <label for="wpide-todo-text" class="screen-reader-text">New task</label>
            <input id="wpide-todo-text" type="text" class="widefat" maxlength="200" placeholder="New task" required>
            <button class="button">Add</button>
            <button type="button" class="button-link" id="wpide-todo-clear">Clear done</button>
        </form>
        <script>
        ( function () {
            var nonce = <?php echo wp_json_encode( wp_create_nonce( 'wpide_todo' ) ); ?>;
            var send = function ( data ) {
                var body = new FormData();
                body.append( 'action', 'wpide_todo' );
                body.append( 'nonce', nonce );
                Object.keys( data ).forEach( function ( key ) { body.append( key, data[ key ] ); } );
                return fetch( ajaxurl, { method: 'POST', credentials: 'same-origin', body: body } ).then( function () { window.location.reload(); } );
            };
            document.getElementById( 'wpide-todo-form' ).addEventListener( 'submit', function ( event ) {
                event.preventDefault();
                send( { op: 'add', text: document.getElementById( 'wpide-todo-text' ).value } );
            } );
            document.getElementById( 'wpide-todo-list' ).addEventListener( 'change', function ( event ) {
                if ( event.target.dataset.index !== undefined ) { send( { op: 'toggle', index: event.target.dataset.index } ); }
            } );
            document.getElementById( 'wpide-todo-clear' ).addEventListener( 'click', function () { send( { op: 'clear' } ); } );
        } )();
        </script>
        <?php
    } );
} );

add_action( 'wp_ajax_wpide_todo', function () {
    check_ajax_referer( 'wpide_todo', 'nonce' );
    if ( ! current_user_can( 'edit_others_posts' ) ) {
        wp_send_json_error( null, 403 );
    }

    $items = (array) get_option( 'wpide_todo_items', array() );
    $op    = isset( $_POST['op'] ) ? sanitize_key( $_POST['op'] ) : '';

    if ( 'add' === $op && ! empty( $_POST['text'] ) ) {
        $items[] = array( 'text' => mb_substr( sanitize_text_field( wp_unslash( $_POST['text'] ) ), 0, 200 ), 'done' => false );
    } elseif ( 'toggle' === $op && isset( $_POST['index'], $items[ absint( $_POST['index'] ) ] ) ) {
        $items[ absint( $_POST['index'] ) ]['done'] = empty( $items[ absint( $_POST['index'] ) ]['done'] );
    } elseif ( 'clear' === $op ) {
        $items = array_filter( $items, function ( $item ) {
            return empty( $item['done'] );
        } );
    }

    update_option( 'wpide_todo_items', array_values( $items ), false );
    wp_send_json_success();
} );
```

## Notes

Tasks are stored in one option; finished tasks stay listed until someone clicks "Clear done".

## How to use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "Shared To-Do List Widget" in its snippet library and add it in one click; or create a new PHP snippet in WPIDE (or any code snippets plugin) and paste the code above. More snippets: https://wpide.com/library/
