David Carter
David Carter

Reputation: 11

GWTP single slot getChild always returns null

Using GWTP, I have a page with two single slot elements that get dynamically loaded with widgets. This works fine and the widget displays. When I try to get the contents of the slot using getChild, it always returns a null value indicating the slot is empty. I'm stuck.

The problem code is in the updateAddresses() method in the view class, which is called when I try to save the changes.

The presenter class:

import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.web.bindery.event.shared.EventBus;
import com.gwtplatform.mvp.client.HasUiHandlers;
import com.gwtplatform.mvp.client.Presenter;
import com.gwtplatform.mvp.client.View;
import com.gwtplatform.mvp.client.annotations.NameToken;
import com.gwtplatform.mvp.client.annotations.ProxyStandard;
import com.gwtplatform.mvp.client.presenter.slots.SingleSlot;
import com.gwtplatform.mvp.client.proxy.PlaceManager;
import com.gwtplatform.mvp.client.proxy.ProxyPlace;
import com.gwtplatform.mvp.shared.proxy.PlaceRequest;

import ca.davidcarter.sessionmanager.client.application.ApplicationPresenter;
import ca.davidcarter.sessionmanager.client.application.widget.contact.address.AddressWidgetPresenter;
import ca.davidcarter.sessionmanager.client.application.widget.contact.email.EmailWidgetPresenter;
import ca.davidcarter.sessionmanager.client.application.widget.contact.phone.PhoneWidgetPresenter;
import ca.davidcarter.sessionmanager.client.application.widget.contact.social.SocialMediaWidgetPresenter;
import ca.davidcarter.sessionmanager.client.application.widget.contact.website.WebsiteWidgetPresenter;
import ca.davidcarter.sessionmanager.client.dto.ContactDTO;
import ca.davidcarter.sessionmanager.client.events.GenericErrorEvent;
import ca.davidcarter.sessionmanager.client.events.UpdatedContactEvent;
import ca.davidcarter.sessionmanager.client.place.NameTokens;
import ca.davidcarter.sessionmanager.client.place.ParameterTokens;
import ca.davidcarter.sessionmanager.client.service.ContactsServiceAsync;

/**
 * @author dcarter
 *
 */
public class ContactPresenter extends Presenter<ContactPresenter.MyView, ContactPresenter.MyProxy>
    implements IContactUiHandlers {

    interface MyView extends View, HasUiHandlers<IContactUiHandlers> {
        void refreshView(ContactDTO model);
    }

    @ProxyStandard
    @NameToken(NameTokens.contact)
    interface MyProxy extends ProxyPlace<ContactPresenter> {
    }

    @Inject Provider<AddressWidgetPresenter> addressWidgetProvider;
    @Inject Provider<PhoneWidgetPresenter> phoneWidgetProvider;
    @Inject Provider<EmailWidgetPresenter> emailWidgetProvider;
    @Inject Provider<SocialMediaWidgetPresenter> socialWidgetProvider;
    @Inject Provider<WebsiteWidgetPresenter> websiteWidgetProvider;

    public static SingleSlot<AddressWidgetPresenter> SLOT_MAILING_ADDRESS = new SingleSlot<AddressWidgetPresenter>();
    public static SingleSlot<AddressWidgetPresenter> SLOT_SHIPPING_ADDRESS = new SingleSlot<AddressWidgetPresenter>();

    private final PlaceManager placeManager;
    private ContactDTO m_model;

    @Inject
    ContactPresenter(
            EventBus eventBus,
            MyView view,
            MyProxy proxy,
            PlaceManager placeManager) {
        super(eventBus, view, proxy, ApplicationPresenter.SLOT_MAIN);

        this.placeManager = placeManager;

        getView().setUiHandlers(this);
    }

    private ContactsServiceAsync getContactsService() {
        return ApplicationPresenter.getContactsService();
    }

    @Override
    public void prepareFromRequest(PlaceRequest request) {
        // Get the pass in parameters
        String contactId = request.getParameter(ParameterTokens.CONTACT_ID, "-1");
        if (contactId.equals("-1")) {
            // create a new contact
            createContact();
        } else {
            // edit an existing contact
            editContact(contactId);
        }
    }

//    @Override
//    protected void onBind() {
//      super.onBind();
//      
//      refreshView();
//    }

    private void createContact() {
        ContactDTO model = new ContactDTO();

        setModel(model);

        getProxy().manualReveal(ContactPresenter.this);
    }

    private void editContact(String contactId) {

        AsyncCallback<ContactDTO> callback = new AsyncCallback<ContactDTO>() {
            @Override
            public void onFailure(Throwable caught) {
                GenericErrorEvent.fire(ContactPresenter.this, "Unable to edit the contact", caught.getLocalizedMessage());

                getProxy().manualRevealFailed();
            }

            @Override
            public void onSuccess(ContactDTO result) {
                // Clone the result so we can discard any changes on cancel
                setModel(new ContactDTO(result));

                getProxy().manualReveal(ContactPresenter.this);
            }
        };

        getContactsService().getContact(Long.parseLong(contactId), callback);
    }

    private void setModel(ContactDTO model) {
        m_model = model;
        refreshView();
    }

    private void refreshView() {
        getView().refreshView(m_model);
    }

    @Override
    public void onSave() {
        saveModel(m_model);
    }

    private void saveModel(ContactDTO model) {

        AsyncCallback<ContactDTO> callback = new AsyncCallback<ContactDTO> () {
            @Override
            public void onFailure(Throwable caught) {
                GenericErrorEvent.fire(ContactPresenter.this, "Unable to save the contact", caught.getLocalizedMessage());
            }

            @Override
            public void onSuccess(ContactDTO result) {
                // Close on a successful save only
                UpdatedContactEvent.fire(ContactPresenter.this, result);

                onExit();
            }
        };

        getContactsService().update(model, callback);
    }

    @Override
    public void onExit() {
        PlaceRequest placeRequest = new PlaceRequest.Builder()
                .nameToken(NameTokens.contacts)
                .build();

        placeManager.revealPlace(placeRequest);
    }

    @Override
    public AddressWidgetPresenter getAddressWidget() {
        return addressWidgetProvider.get();
    }

    @Override
    public PhoneWidgetPresenter getPhoneWidget() {
        return phoneWidgetProvider.get();
    }

    @Override
    public EmailWidgetPresenter getEmailWidget() {
        return emailWidgetProvider.get();
    }

    @Override
    public SocialMediaWidgetPresenter getSocialWidget() {
        return socialWidgetProvider.get();
    }

    @Override
    public WebsiteWidgetPresenter getWebsiteWidget() {
        return websiteWidgetProvider.get();
    }

    @Override
    public ContactDTO getModel() {
        return m_model;
    }

    @Override
    public AddressWidgetPresenter getMailingAddressWidget() {
        return getChild(SLOT_MAILING_ADDRESS);
    }

    @Override
    public AddressWidgetPresenter getShippingAddressWidget() {
        return getChild(SLOT_SHIPPING_ADDRESS);
    }
}

The view class

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.inject.Inject;

import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Widget;
import com.gwtplatform.mvp.client.ViewWithUiHandlers;

import ca.davidcarter.sessionmanager.client.application.widget.contact.address.AddressWidgetPresenter;
import ca.davidcarter.sessionmanager.client.dto.ContactAddressDTO;
import ca.davidcarter.sessionmanager.client.dto.ContactDTO;
import ca.davidcarter.sessionmanager.client.dto.ContactEmailDTO;
import ca.davidcarter.sessionmanager.client.dto.ContactPhoneDTO;
import ca.davidcarter.sessionmanager.client.dto.ContactSocialMediaDTO;
import ca.davidcarter.sessionmanager.client.dto.ContactWebsiteDTO;
import gwt.material.design.addins.client.combobox.MaterialComboBox;
import gwt.material.design.addins.client.combobox.events.SelectItemEvent;
import gwt.material.design.client.ui.MaterialButton;
import gwt.material.design.client.ui.MaterialCheckBox;
import gwt.material.design.client.ui.MaterialDatePicker;
import gwt.material.design.client.ui.MaterialPanel;
import gwt.material.design.client.ui.MaterialTextBox;

/**
 * @author dcarter
 *
 */
public class ContactView extends ViewWithUiHandlers<IContactUiHandlers> implements ContactPresenter.MyView {
    interface Binder extends UiBinder<Widget, ContactView> {
    }

    @UiField MaterialComboBox<String> contactSalutation;
    @UiField MaterialTextBox contactFirstName;
    @UiField MaterialTextBox contactMiddleName;
    @UiField MaterialTextBox contactLastName;
    @UiField MaterialDatePicker contactDOB;

    @UiField MaterialPanel contactMailingAddress;
    @UiField MaterialPanel contactShippingAddress;
    @UiField MaterialCheckBox contactMailingIsShipping;
    @UiField MaterialPanel contactPhones;
    @UiField MaterialPanel contactEmail;
    @UiField MaterialPanel contactWebsite;
    @UiField MaterialPanel contactSocial;

    @UiField MaterialButton contactCancel;
    @UiField MaterialButton contactSave;

//    @UiField MaterialLink contactAddPhone;
//    @UiField MaterialLink contactAddEmail;
//    @UiField MaterialLink contactAddWebsite;
//    @UiField MaterialLink contactAddSocial;

    ContactAddressDTO shippingAddress; // Scratch value, may be null

    @Inject
    ContactView(Binder uiBinder) {
        initWidget(uiBinder.createAndBindUi(this));

        initSalutations();
        contactDOB.setDateMax(new Date()); // DOB can't be later than today

        bindSlot(ContactPresenter.SLOT_MAILING_ADDRESS, contactMailingAddress);
        bindSlot(ContactPresenter.SLOT_SHIPPING_ADDRESS, contactShippingAddress);
    }

    @Override
    protected void onAttach() {
        super.onAttach();

        Element splash = Document.get().getElementById("splashscreen");
        if (splash != null)
            splash.removeFromParent();
    }

    @Override
    public void refreshView(ContactDTO model) {
        if (model != null) {
            contactSalutation.setSingleValue(model.getSalutation());
            contactFirstName.setText(model.getFirstName());
            contactMiddleName.setText(model.getMiddleName());
            contactLastName.setText(model.getLastName());
            if (model.getDateOfBirth() == null)
                contactDOB.clear();
            else
                contactDOB.setDate(model.getDateOfBirth());

            setMailingAddress(model.getAddressList());
            setShippingAddress(model.getAddressList());
            setPhones(model.getPhoneList());
            setEmail(model.getEmailList());
            setWebsite(model.getWebsiteList());
            setSocial(model.getSocialList());
        }
    }

    @UiHandler("contactSalutation")
    void onPreviewHostClick(SelectItemEvent<String> event) {

    }

    @UiHandler("contactAddPhone")
    protected void onContactAddPhone (ClickEvent e) {
    }

    @UiHandler("contactAddEmail")
    protected void onContactAddEmail (ClickEvent e) {
    }

    @UiHandler("contactAddWebsite")
    protected void onContactAddWebsite (ClickEvent e) {
    }

    @UiHandler("contactAddSocial")
    protected void onContactAddSocial (ClickEvent e) {
    }

    @UiHandler("contactCancel")
    protected void onContactCancel (ClickEvent e) {
        getUiHandlers().onExit();
    }

    @UiHandler("contactSave")
    protected void onContactSave (ClickEvent e) {
        updateModel();
        getUiHandlers().onSave();
    }

    /**
     * The first address is the mailing address
     * 
     * @param addressList
     */
    private void setMailingAddress(List<ContactAddressDTO> addressList) {
        ContactAddressDTO address;
        if (addressList == null || addressList.isEmpty()) {
            // If no mailing address exists, create an empty one. This is by
            // default the shipping address
            address = new ContactAddressDTO();
            shippingAddress = null;
            address.setShippingAddress(true);
        } else {
            address = addressList.get(0);
        }

        AddressWidgetPresenter widget = getUiHandlers().getAddressWidget();
        setInSlot(ContactPresenter.SLOT_MAILING_ADDRESS, widget);
        widget.setAddress(address);

        contactMailingIsShipping.setValue(address.isShippingAddress());
    }

    /**
     * There may be 0 or more shipping addresses, currently only supporting 1
     * 
     * @param addressList
     */
    private void setShippingAddress(List<ContactAddressDTO> addressList) {
        if (addressList.size() <= 1 || addressList.get(0).isShippingAddress()) {
            setInSlot(ContactPresenter.SLOT_SHIPPING_ADDRESS, null);
        } else {
            AddressWidgetPresenter widget = getUiHandlers().getAddressWidget();
            setOrCreateShippingAddress(addressList);
            widget.setAddress(shippingAddress);
            setInSlot(ContactPresenter.SLOT_SHIPPING_ADDRESS, widget);
        }
    }

    private void setOrCreateShippingAddress(List<ContactAddressDTO> addressList) {
        // Update if null
        if (shippingAddress == null && addressList.size() > 1)
            shippingAddress = addressList.get(1);

        // Create if empty
        if (shippingAddress == null)
            shippingAddress = new ContactAddressDTO();
    }

    private void setPhones(List<ContactPhoneDTO> phoneList) {
        for (ContactPhoneDTO phone : phoneList)
            addPhone(phone);
    }

    private void addPhone(ContactPhoneDTO phone) {

    }

    private void setEmail(List<ContactEmailDTO> emailList) {
        for (ContactEmailDTO email : emailList)
            addEmail(email);
    }

    private void addEmail(ContactEmailDTO email) {

    }

    private void setWebsite(List<ContactWebsiteDTO> websiteList) {
        for (ContactWebsiteDTO website : websiteList)
            addWebsite(website);
    }

    private void addWebsite(ContactWebsiteDTO website) {

    }

    private void setSocial(List<ContactSocialMediaDTO> socialList) {
        for (ContactSocialMediaDTO social : socialList)
            addSocial(social);
    }

    private void addSocial(ContactSocialMediaDTO social) {

    }

    private void initSalutations() {
        contactSalutation.addItem("Mr");
        contactSalutation.addItem("Mrs");
        contactSalutation.addItem("Miss");
        contactSalutation.addItem("Ms");
        contactSalutation.addItem("Dr");
    }

    private void updateModel() {
        ContactDTO model = getUiHandlers().getModel();

        model.setSalutation(contactSalutation.getSingleValue());
        model.setFirstName(contactFirstName.getText());
        model.setMiddleName(contactMiddleName.getText());
        model.setLastName(contactLastName.getText());
        model.setDateOfBirth(contactDOB.getDate());

        updateAddresses(model);
//      
//      setPhones(model.getPhoneList());
//      setEmail(model.getEmailList());
//      setWebsite(model.getWebsiteList());
//      setSocial(model.getSocialList());
    }

    private void updateAddresses(ContactDTO model) {
        List<ContactAddressDTO> addresses = new ArrayList<>();
        AddressWidgetPresenter widget = getUiHandlers().getMailingAddressWidget();
        if (widget != null) {
            ContactAddressDTO address = widget.getAddress();
            addresses.add(address);

            if (!address.isShippingAddress()) {
                widget = getUiHandlers().getShippingAddressWidget();
                if (widget == null) {
                    addresses.get(0).setShippingAddress(true);
                } else {
                    address = widget.getAddress();
                    addresses.add(address);
                }
            }
        }

        if (addresses.size() > 0)
            model.setAddressList(addresses);
        else
            model.setAddressList(null);
    }

}

Upvotes: 0

Views: 38

Answers (0)

Related Questions