Create an Acme Part Wizard
Earlier, we had created a new subtype AcmePart of the type Part. In this example, we will create a new wizard to capture specific details of the Acme part. The wizard will consist of three steps—Set Acme Part Attributes, Set Attachments, More Custom Attributes.
* 
By default, the Set Attachments step is not displayed in the wizard. To view the step, set the preference Attachments on parts to Yes.
For information on creating a wizard, see Windchill Client Architecture Wizard.
Author Wizard JSP (Set Acme Part Attributes) 
1. Specify the wizard steps in the wizard file createCustomPart.jsp at the location <customizationRootDirectory>\<Acme_WizardModule>\main\src_web\netmarkets\jsp\<custom>\<custompart>.
<jca:wizard helpSelectorKey="${helpKey}" buttonList="${buttonList}" title="${wizardTitle}"
formProcessorController="com.ptc.windchill.enterprise.part.forms.CreatePartAndCADDocFormProcessorController" >
<jca:wizardStep action="defineCustomItemAttributesWizStep" objectHandle="<%=PartConstants.ObjectHandles.PART%>" type="custompart"/>
<jca:wizardStep action="attachments_step" type="attachments" />
<jca:wizardStep action="moreCustomAttributesWizStep1" objectHandle="<%=PartConstants.ObjectHandles.PART%>" type="custompart"/>
</jca:wizard>
2. Define the action defineCustomItemAttributesWizStep for the first step—Set Acme Part attributes, in AcmePartclient-actions.xml.
<action name="defineCustomItemAttributesWizStep"
afterVK="setAttributesWizStep"
id="defineCustomItemAttributesWizStep"
preloadWizardPage="false" required="true"
resourceBundle="com.acme.custompart.CustomPartResource">
<component name="defineCustomItemAttributesWizStep"
typeBased="true" windowType="wizard_step" />
</action>
3. Define the resource bundle for defineCustomItemAttributesWizStep in CustomPartResource.java.
@RBEntry("Set Acme Part Attributes")
public static final String PRIVATE_CONSTANT_46 = "custompart.defineCustomItemAttributesWizStep.description";
@RBEntry("Set Acme Part Attributes")
public static final String PRIVATE_CONSTANT_47 = "custompart.defineCustomItemAttributesWizStep.title";
@RBEntry("Set Acme Part Attributes")
public static final String PRIVATE_CONSTANT_48 = "custompart.defineCustomItemAttributesWizStep.tooltip";
4. Define the component defineCustomItemAttributesWizStep as given.
@ComponentBuilder(value = "defineCustomItemAttributesWizStep")
@TypeBased(value = "WCTYPE|wt.part.WTPart|com.acme.AcmePartType")
public class CustomPartDefineItemAttributesWizStepBuilder extends AbstractComponentBuilder {

@Override
public final Object buildComponentData(ComponentConfig config, ComponentParams params) throws Exception {
return Collections.EMPTY_LIST;
}

@Override
public final ComponentConfig buildComponentConfig(ComponentParams params) throws WTException {

// set the mode to CREATE
params.setAttribute(ComponentMode.class.getName(), ComponentMode.CREATE.toString());

ComponentConfigFactory factory = getComponentConfigFactory();
TableConfig table = factory.newTableConfig();
table.setView("/custom/newwizard/custompart/defineCustomItemAttributesWizStep.jsp");
return table;
}
}
5. Author the file defineCustomItemAttributesWizStep.jsp at the location <customizationRootDirectory>\<Acme_WizardModule>\main\src_web\WEB-INF\jsp\<custom>\<newwizard>\<custompart> with the given code snippet.
<%@ taglib uri="http://www.ptc.com/windchill/taglib/jcaMvc" prefix="mvc"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="p" uri="http://www.ptc.com/windchill/taglib/picker"%>
<%@ taglib prefix="wctags" tagdir="/WEB-INF/tags" %>
<%@ taglib prefix="s" uri="http://www.ptc.com/windchill/taglib/subscription"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/components"
prefix="jca"%>

<%@page import="com.ptc.core.components.rendering.guicomponents.TextBox"%>
<%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%>
<%@ include file="/netmarkets/jsp/components/createEditUIText.jspf"%>
<%@ include file="/netmarkets/jsp/components/includeWizBean.jspf"%>

<input id="objectIdentifierInput" type="hidden" disabled="true"
value="There will be provided object identifier..."
style="width: 260px" />

<div id='<%=wt.util.HTMLEncoder.encodeForHTMLAttribute(createBean.getCurrentObjectHandle())%>driverAttributesPane'>
<%@ include file="/netmarkets/jsp/components/defineItemReadOnlyPropertyPanel.jspf"%>
<%@ include file="/netmarkets/jsp/custom/custompart/customDefineItem.jspf"%>
</div>

<mvc:attributesTableWizComponent/>
<%@ include file="/netmarkets/jsp/util/end.jspf"%>
It will render the attributes panel Acme Part Attributes in the Set Acme Part Attributes step and list the attributes defined in the Type and Attribute Management utility.
6. Author the file customDefineItem.jspf at the location <customizationRootDirectory>\<Acme_WizardModule>\main\src_web\netmarkets\jsp\<custom>\<custompart> to add or modify the panel above the Acme Part Attributes panel.
<%@ taglib uri="http://www.ptc.com/windchill/taglib/components" prefix="jca"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@page import="com.ptc.core.components.rendering.guicomponents.ComboBox,
com.ptc.core.meta.common.TypeIdentifier,
com.ptc.core.meta.common.TypeInstanceIdentifier,
wt.util.HTMLEncoder"%><%
String urlForDriverAttributes = "/servlet/TypeBasedIncludeServlet?contextAction=defineItemAttributesPanel";
String encodedObjHandleForJS = "";
if(!"".equals(createBean.getCurrentObjectHandle())) {
encodedObjHandleForJS = HTMLEncoder.encodeForJavascript(createBean.getCurrentObjectHandle());
urlForDriverAttributes += "&currentObjectHandle="+encodedObjHandleForJS;
}
String comboBoxId = createBean.getCurrentObjectHandle() + "createType";
%>

<jca:renderPropertyPanel>
<jca:addPlaceHolder id="${createBean.currentObjectHandle}driverAttributes" />
<c:if test="${createBean.propagationBean != null}">
<jca:propagateComponent preferenceKey="${createBean.propagationBean.preferenceKey}"
label="${createBean.propagationBean.label}"
tooltip="${createBean.propagationBean.tooltip}"/>
</c:if>
</jca:renderPropertyPanel>

<input type="hidden" id="<%=HTMLEncoder.encodeForHTMLAttribute(createBean.getCurrentObjectHandle())%>typeFromTypePicker" value="<%=HTMLEncoder.encodeForHTMLAttribute(createBean.getTypeInstanceIdStringForNewItem("wt.part.WTPart|com.acme.AcmePartType")) %>"/>

<script type="text/javascript">
PTC.onReady(function() {
// load the attributes panel if there is a default value defined for the 'Type' property and the attributes panel has not already been requested
PTC.wizard.loadAttributesPanel("<%=encodedObjHandleForJS%>", "<%=urlForDriverAttributes%>");
});
</script>
Add an Existing Step (Set Attachments) 
This example shows how to add the second step—Set Attachments.
<jca:wizardStep action="attachments_step" type="attachments" />
Add a Custom Step (More Custom Attributes) 
This example shows how to add a custom step—More Custom Attributes.
1. Create a custom layout based on the MVC Java builder class.
2. Author the MVC Java builder class that builds the panel configuration from the layout definition created for the subtype AcmePart.
This layout is already defined on the subtype AcmePart.
package com.acme.wizard.mvc.builders.custompart;

import com.ptc.core.lwc.common.ScreenDefinitionName;
import com.ptc.core.ui.resources.ComponentMode;
import com.ptc.jca.mvc.builders.TypedAttributesPanelBuilder;
import com.ptc.mvc.components.AttributePanelConfig;
import com.ptc.mvc.components.ComponentBuilder;
import com.ptc.mvc.components.ComponentParams;
import com.ptc.mvc.components.TypedAttrLayOutFactory;
import wt.util.WTException;

/**
* This builder builds the attribute panel on the custom step.
*/
@ComponentBuilder("Acme.CustomAttributes")
public class AcmeCustomAttributesBuilder extends TypedAttributesPanelBuilder{

/** The tfactory. */
TypedAttrLayOutFactory tfactory;

/*
* Builds attribute panel to render on custom step of new Acme Part Wizard.
*/
@Override
protected AttributePanelConfig buildAttributePanelConfig(
ComponentParams arg0) throws WTException {
AttributePanelConfig table;
ScreenDefinitionName layout = null;
ComponentMode mode = getComponentMode(arg0);
if (mode.equals(ComponentMode.CREATE)) {
layout = ScreenDefinitionName.CREATE2;
} else if (mode.equals(ComponentMode.EDIT)) {
layout = ScreenDefinitionName.UPDATE2;
}
table = (AttributePanelConfig) tfactory.getAttributePanelConfig(getComponentConfigFactory(), arg0, layout);
table.setComponentMode(mode);

return table;
}

public void setTypedAttrLayOutFactory(TypedAttrLayOutFactory factory) {
this.tfactory = factory;
}
}
3. Configure the above builder component as an action in actions.xml with the given configuration.
<action name="moreCustomAttributesWizStep1" id="moreCustomAttributesWizStep1"
preloadWizardPage="false" required="true" resourceBundle="com.acme.custompart.CustomPartResource">
<component name="Acme.CustomAttributes" windowType="wizard_step" />
</action>
4. Configure the above action as a new custom step on the new wizard.
<jca:wizard helpSelectorKey="${helpKey}" buttonList="${buttonList}" .. >
.
.
<jca:wizardStep action="moreCustomAttributesWizStep1"
objectHandle="<%=PartConstants.ObjectHandles.PART%>"
type="custompart"/>
</jca:wizard>
The custom step More Custom Attributes is added to the wizard.
5. After the MVC builders are created, register the builders:
a. Create a custom.site.xconf file in the <customizationRootDirectory>/xconf folder if it has not been already created.
b. Add the custom.mvc.builders.base-packages property in the custom.site.xconf file. Set the value of the property to the name of the base package.
<AddToProperty name="custom.mvc.builders.base-packages" value="com.acme.wizard.mvc.builders.custompart"/>
Author Form Processor 
1. Add a custom logic in the custom form processor or any server-side validation that needs to be performed on the custom form processor data.
public class CreateCustomPartFormProcessor extends CreatePartFormProcessor {

@Override
public FormResult doOperation(NmCommandBean clientData, List<ObjectBean> objectBeans) throws WTException {
FormResult formResult = new FormResult(FormProcessingStatus.SUCCESS);
List<ObjectBean> partObjectBeanList = objectBeans.stream()
.filter(objectBean -> objectBean.getObjectHandle().equals(PartConstants.ObjectHandles.PART))
.collect(Collectors.toList());

if (!partObjectBeanList.isEmpty()) {
formResult = super.doOperation(clientData, partObjectBeanList);
}

return formResult;
}
}
2. Configure the custom form processor for the create action in AcmePartClient-actions.xml to invoke the form processor for saving the Acme part.
<action name="createCustomPartWizard" ajax="row"
resourceBundle="com.acme.custompart.CustomPartResource">
<command class="com.acme.custompart.forms.CreateCustomPartFormProcessor" method="execute"
url="/ptc1/custom/custompart/createCustomPartWizard?revisionMode=create&showNewCADDocStep=true&hideAssociatePart=true"
onClick="validateCreateLocation(event)"
windowType="popup" />
</action>
Author Validators 
1. Specify the conditions to control the visibility of the action Create Acme Part.
As per the logic given in this example, the action will be rendered only in the PDMLink container.
public class AcmePartActionValidator extends DefaultUIComponentValidator {

@Override
public UIValidationResultSet performFullPreValidation(UIValidationKey validationKey,
UIValidationCriteria validationCriteria, Locale locale)
throws WTException {

UIValidationResultSet resultSet = UIValidationResultSet.newInstance();
UIValidationStatus status = UIValidationStatus.HIDDEN;

WTContainerRef containerRef = validationCriteria.getParentContainer();
Class containerClass = null;

if (null != containerRef) {
containerClass = containerRef.getReferencedClass();
}

if (null != containerClass && PDMLinkProduct.class.isAssignableFrom(containerClass)) {
status = UIValidationStatus.ENABLED;
}
UIValidationResult result = UIValidationResult.newInstance(validationKey, status);
resultSet.addResult(result);
return resultSet;
}
}
2. Configure the validator in the custom file NewWizard-service.properties.xconf at the location <customizationRootDirectory>\<Acme_WizardModule>\main\xconf.
<Service context="default" name="com.ptc.core.ui.validation.UIComponentValidator">
<Option serviceClass="com.acme.custompart.validators.AcmePartActionValidator"
requestor="null" selector="createCustomPartWizard" cardinality="duplicate" />
</Service>
Was this helpful?