• Resolved traveler

    (@visualeight)


    I have a custom post type with custom fields that a site user will complete on the front-end logged in as a subscriber. It will only show the page to a logged in user, will allow them to create, update/edit their profile. My code is working, but not all the way, none of the custom fields are updating, although I can update the title and the page slug. So the issue is the core page properties are updating but the custom fields from the page will not update. The CPT is set to only show the title and custom fields.

    My jquery/ajax is in a function run on a click event:

    updateProfile() {
            
            const ourUpdatedPost = {
                'title': this.profileWrapper.find('input[name="first-name"]').val() + ' ' + this.profileWrapper.find('input[name="last-name"]').val(),
                'slug': this.profileWrapper.find('input[name="first-name"]').val() + '-' + this.profileWrapper.find('input[name="last-name"]').val(),
                'firstName': this.profileWrapper.find('input[name="first-name"]').val(),
                'lastName': this.profileWrapper.find('input[name="last-name"]').val(),
                'email': this.profileWrapper.find('input[name="email-address"]').val(),
                'cellPhone': this.profileWrapper.find('input[name="cell-phone"]').val(),
                'homePhone': this.profileWrapper.find('input[name="home-phone"]').val(),
                'officePhone': this.profileWrapper.find('input[name="office-phone"]').val(),
                'homeAddress': this.profileWrapper.find('input[name="home-address"]').val(),
                'city': this.profileWrapper.find('input[name="city"]').val(),
                'state': this.profileWrapper.find('input[name="state"]').val(),
                'zipCode': this.profileWrapper.find('input[name="zip-code"]').val(),
                'gender': this.profileWrapper.find('input[name="gender"]').val(),
                'dateOfBirth': this.profileWrapper.find('input[name="date-of-birth"]').val(),
                'rolodexId': this.profileWrapper.find('input[name="rolodex-id"]').val(),
                'staffId': this.profileWrapper.find('input[name="staff-id"]').val(),
                'department': this.profileWrapper.find('input[name="department"]').val(),
                'jobTitle': this.profileWrapper.find('input[name="job-title"]').val(),
                'supervisorsFirstName': this.profileWrapper.find('input[name="supervisors-first-name"]').val(),
                'supervisorsLastName': this.profileWrapper.find('input[name="supervisors-last-name"]').val(),
                'userProfileIntro': this.profileWrapper.find('textarea[name="user-profile-intro"]').val()
            }
            console.log(ourUpdatedPost);
    
            $.ajax({
                beforeSend: (xhr) => {
                    xhr.setRequestHeader('X-WP-Nonce', leadershipData.nonce);
                },
                url: leadershipData.root_url + '/wp-json/wp/v2/profiles/' + this.profileWrapper.data('id'),
                type: 'PUT',
                data: ourUpdatedPost,
                success: (response) => {
                    this.makeProfileReadOnly(this.inputFields);
                    console.log('Congrats a success!');
                    console.log(response);
                },
                error: (response) => {
                    console.log('No Sorry');
                    console.log(response); 
                }
            });
        }

    The first two properties for ‘title’ and ‘slug’ will update, but none of the others will. The properties for ‘firstName’ and ‘lastName’ use the same selectors as the title and slug, but they won’t update. It does not throw any error, I get the success response, but none of the custom fields will update and on page refresh have reverted back to the placeholder.

    Here is the json response at /wp-json/wp/v2/profiles?id=434:

    {
    id: 434,
    date: "2020-04-01T22:36:41",
    date_gmt: "2020-04-01T22:36:41",
    guid: {
    rendered: "http://devleadership.staging.wpengine.com/?post_type=profile&p=434"
    },
    modified: "2020-05-19T06:18:48",
    modified_gmt: "2020-05-19T06:18:48",
    slug: "horatio-jones",
    status: "publish",
    type: "profile",
    link: "http://devleadership.staging.wpengine.com/profile/horatio-jones/",
    title: {
    rendered: "Horatio Jones"
    },
    template: "",
    meta: [ ],
    firstName: "Stephen",
    lastName: "Jones",
    email: "sjones@yahoo.com",
    cellPhone: "322-333-3333",
    homePhone: "213-555-5555",
    officePhone: "818-333-3333",
    homeAddress: "21 Jumping Jack Terrace",
    city: "Alhambra",
    state: "CA",
    zipCode: "90210",
    gender: "Male",
    dateOfBirth: "11/04/1984",
    rolodexId: "679769",
    staffId: "98798798",
    department: "Human Resources",
    jobTitle: "Leader",
    supervisorsFirstName: "Siddarth",
    supervisorsLastName: "Girade",
    userProfileIntro: "Hello my name is Stephen, I like to help people learn and be the best person I can. Go Dodgers!",
    _links: {
    self: [
    {
    href: "http://devleadership.staging.wpengine.com/wp-json/wp/v2/profiles/434"
    }
    ],
    collection: [
    {
    href: "http://devleadership.staging.wpengine.com/wp-json/wp/v2/profiles"
    }
    ],
    about: [
    {
    href: "http://devleadership.staging.wpengine.com/wp-json/wp/v2/types/profile"
    }
    ],
    wp:attachment: [
    {
    href: "http://devleadership.staging.wpengine.com/wp-json/wp/v2/media?parent=434"
    }
    ],
    curies: [
    {
    name: "wp",
    href: "https://api.w.org/{rel}",
    templated: true
    }
    ]
    }
    }

    All of the above custom fields were registered in this pattern:

    register_rest_field('profile', 'firstName', array(
           'get_callback' => function() {
               return get_field('first_name');
           }
    	));

    Any thoughts on what I’m missing?

Viewing 6 replies - 1 through 6 (of 6 total)
  • Moderator bcworkz

    (@bcworkz)

    You’re setting all of your meta fields as primary fields. They all need to fall under the primary “meta” field. Use register_meta() instead of register_rest_field() for these fields

    Thread Starter traveler

    (@visualeight)

    Thanks for your reply. I replaced the ‘register_rest_field()’ with this format:

    register_meta('post', 'first_name', [
    		'object_subtype'	=> 'profile',
    		'show_in_rest'		=> true
    	]);

    And it shifted how the data was displayed in json as expected to:

    {
    id: 434,
    date: "2020-04-01T22:36:41",
    date_gmt: "2020-04-01T22:36:41",
    guid: {
    rendered: "http://devleadership.staging.wpengine.com/?post_type=profile&p=434"
    },
    modified: "2020-05-19T18:55:18",
    modified_gmt: "2020-05-19T18:55:18",
    slug: "hansel-gretel",
    status: "publish",
    type: "profile",
    link: "http://devleadership.staging.wpengine.com/profile/hansel-gretel/",
    title: {
    rendered: "Hansel Gretel"
    },
    template: "",
    meta: {
    first_name: [
    "Stephen"
    ],
    last_name: [
    "Jones"
    ],
    email_address: [
    "sjones@yahoo.com"
    ],
    cell_phone: [
    "322-333-3333"
    ],

    …and down the list of custom fields using that same pattern. It still behaves the same way, I get a success message and only the title and slug update with the ACF values for first_name and last_name, but the actual fields displaying first name and last name do not update, they revert back to what they were.

    Am I trying to access the post meta fields incorrectly in the Ajax call?

    updateProfile() {
            
            const ourUpdatedPost = {
                'title': this.profileWrapper.find('input[name="first-name"]').val() + ' ' + this.profileWrapper.find('input[name="last-name"]').val(),
                'slug': this.profileWrapper.find('input[name="first-name"]').val() + '-' + this.profileWrapper.find('input[name="last-name"]').val(),
                'first_name': this.profileWrapper.find('input[name="first-name"]').val(),
                'last_name': this.profileWrapper.find('input[name="last-name"]').val(),
                'email': this.profileWrapper.find('input[name="email-address"]').val(),
                'cell_phone': this.profileWrapper.find('input[name="cell-phone"]').val(),
                'home_phone': this.profileWrapper.find('input[name="home-phone"]').val(),
                'office_phone': this.profileWrapper.find('input[name="office-phone"]').val(),
                'home_address': this.profileWrapper.find('input[name="home-address"]').val(),
                'city': this.profileWrapper.find('input[name="city"]').val(),
                'state': this.profileWrapper.find('input[name="state"]').val(),
                'zip_code': this.profileWrapper.find('input[name="zip-code"]').val(),
                'gender': this.profileWrapper.find('input[name="gender"]').val(),
                'date_of_birth': this.profileWrapper.find('input[name="date-of-birth"]').val(),
                'rolodex_id': this.profileWrapper.find('input[name="rolodex-id"]').val(),
                'staff_id': this.profileWrapper.find('input[name="staff-id"]').val(),
                'department': this.profileWrapper.find('input[name="department"]').val(),
                'job_title': this.profileWrapper.find('input[name="job-title"]').val(),
                'supervisors_first_name': this.profileWrapper.find('input[name="supervisors-first-name"]').val(),
                'supervisors_last_name': this.profileWrapper.find('input[name="supervisors-last-name"]').val(),
                'user_profile_intro': this.profileWrapper.find('textarea[name="user-profile-intro"]').val()
            }
            console.log(ourUpdatedPost);
    
            $.ajax({
                beforeSend: (xhr) => {
                    xhr.setRequestHeader('X-WP-Nonce', leadershipData.nonce);
                },
                url: leadershipData.root_url + '/wp-json/wp/v2/profiles/' + this.profileWrapper.data('id'),
                type: 'PUT',
                data: ourUpdatedPost,
                success: (response) => {
                    this.makeProfileReadOnly(this.inputFields);
                    console.log('Congrats a success!');
                    console.log(response);
                },
                error: (response) => {
                    console.log('No Sorry');
                    console.log(response); 
                }
            });
        }
    Moderator bcworkz

    (@bcworkz)

    Yes, your data structure passed by Ajax is off. You’ve altered the API field types correctly, but not the passed data. They’re all still primary values. Meta values should be passed as an object under “meta:” primary key. The data structure submitted should comply with the user schema of the API. The resulting JSON should look like the JSON returned from the API. (except with updated values of course)

    Thread Starter traveler

    (@visualeight)

    Update, I changed a lot around, now I have it working almost. The only issue is the fields that have spaces are being sent as strings but returned as arrays so only the first word of that string shows without adjusting for the return array value in the page template. I imagine this has to do with me not using register_rest_route()?

    Here is my jquery:

    updateProfile() {
    
            this.title = this.firstName.val() + ' ' + this.lastName.val();
            this.slug = this.firstName.val() + ' - ' + this.lastName.val();
            this.firstName = this.firstName.val();
            this.lastName = this.lastName.val();
            this.email = this.email.val();
            this.cellPhone = this.cellPhone.val();
            this.homePhone = this.homePhone.val();
            this.officePhone = this.officePhone.val();
            this.homeAddress = this.homeAddress.val();
            this.city = this.city.val();
            this.state = this.state.val();
            this.zipCode = this.zipCode.val();
            this.gender = this.gender.val();
            this.dateOfBirth = this.dateOfBirth.val();
            this.rolodexId = this.rolodexId.val();
            this.staffId = this.staffId.val();
            this.department = this.department.val();
            this.jobTitle = this.jobTitle.val();
            this.supervisorsFirstName = this.supervisorsFirstName.val();
            this.supervisorsLastName = this.supervisorsLastName.val();
            this.userProfileIntro = this.userProfileIntro.val();
    
            $.ajax({
                beforeSend: (xhr) => {
                    xhr.setRequestHeader('X-WP-Nonce', leadershipData.nonce);
                },
                url: leadershipData.root_url + '/wp-json/wp/v2/profiles/' + this.profileWrapper.data('id'),
                type: 'PUT',
                data: {
                    title: this.title,
                    slug: this.slug,
                    meta: {
                        first_name: this.firstName,
                        last_name: this.lastName,
                        email_address: this.email,
                        cell_phone: this.cellPhone,
                        home_phone: this.homePhone,
                        office_phone: this.officePhone,
                        home_address: this.homeAddress,
                        city: this.city,
                        state: this.state,
                        zip_code: this.zipCode,
                        gender: this.gender,
                        date_of_birth: this.dateOfBirth,
                        rolodex_id: this.rolodexId,
                        staff_id: this.staffId,
                        department: this.department,
                        job_title: this.jobTitle,
                        supervisors_first_name: this.supervisorsFirstName,
                        supervisors_last_name: this.supervisorsLastName,
                        user_profile_page_intro: this.userProfileIntro
                    }
                    
                },
                success: (response) => {
                    this.makeProfileReadOnly(this.inputFields);
                    console.log('Congrats a success!');
                    console.log(response);
                },
                error: (response) => {
                    console.log('No Sorry');
                    console.log(response); 
                }
            });
        }

    I have my PHP custom fields registered in this format:

    register_meta('post', 'first_name', [
    		'object_subtype'	=> 'profile',
            'show_in_rest'		=> true,
            'type'              => 'string',
    	]);
    	register_meta('post', 'last_name', [
    		'object_subtype'	=> 'profile',
            'show_in_rest'		=> true,
            'type'              => 'string'
    	]);
    	register_meta('post', 'email_address', [
    		'object_subtype'	=> 'profile',
            'show_in_rest'		=> true,
            'type'              => 'string'
    	]);

    Using 'type' => 'string' did not function as I thought, which was that it would force that value to be a string.

    What is the next step to look into so that my input fields and text fields with multiple words within them aren’t converted to arrays before being sent back to the page?

    Moderator bcworkz

    (@bcworkz)

    Maybe try including 'single' => true, in each register_meta() call.

    Thread Starter traveler

    (@visualeight)

    Hey bcworkz, that worked. Funny thing, I guess ‘single’ defaults to false, because before I added it previously I was having the issue of not all the words in a string being saved. However, adding it as single=>true did fix this issue.

    Thanks for your advice.

Viewing 6 replies - 1 through 6 (of 6 total)

The topic ‘Update CPT with custom fields with REST API’ is closed to new replies.