cx:component-class

Purpose

Defines the structure of all components of a particular type, specifically the references it has to other components. Please refer to the topic entitled Component types and classes for more information.

Contained by

Contains

Attribute groups

Attributes

Attribute Description Type Default Options Use
defines

A set of aspects completely defined by the component class. The component class author must indicate which aspects of the component class have been fully defined and which have not to allow the validator to differentiate between a partially incomplete component class and a complete component class. That in turn allows the validator to determine whether a potential logical error is actually an error or simply a case of missing information.

The 'reference-types' aspect covers the following information about each reference: name, component types, structural relationship, and cardinality. 'all' indicates that a given component class definition defines all aspects of the component class. Refer to the topic entitled Component types and classes for more information.

xs:string   all, reference-types optional 
implements The space-separated list of component types that the class implements. The list of components must be consistent with the client-side implementation as otherwise it will prevent the server from detecting errors correctly. xs:QName     optional 
name The optional name of the class. The name defines a new component type that inherits from those types that it implements. xs:QName     optional 

Example

<html xmlns="http://www.w3.org/2002/06/xhtml2"
  xmlns:cf2="http://www.volantis.com/xmlns/2009/07/cf2"
  xmlns:cst="http://www.volantis.com/xmlns/2009/07/cf2/template"
  xmlns:cx="http://www.volantis.com/xmlns/2010/07/cf2/cx"
  xmlns:mcs="http://www.volantis.com/xmlns/2006/01/xdime/mcs"
  xmlns:my="http://www.mycomponents"
  xmlns:ui="http://www.volantis.com/xmlns/2009/07/cf2/ui"
  xmlns:car="http://www.cars/">
  <head>
    <title>Custom Component Example</title>
    <meta property='cf2:validation-mode' about='#PoorDriver'>strict</meta>
    
    <!--
     ! This page makes use of Observable Property Prototype and so should explicitly indicate
     ! that by providing an mcs:script element that references an mscr file that imports those
     ! features. Instead this relies on the ui:button element importing the required feature
     ! into the page. This is probably not the best way but is allowed as a button is
     ! explicitly defined as importing that feature.
     !-->
    
    <!--
     ! Car Class
     !-->
    <cx:component-class defines="reference-types" name="car:Car" id="Car">
      <mcs:script type="text/javascript">
        // ==================================================
        // JavaScript representation of Car
        // ==================================================
        var Car = V$.Class.create();
        Car.mixin(V$.cf2.OPSet);
        V$.cf2.OPProto.add(Car, "owner", {});
        Car.methods({
          initialize: function() {
            V$.cf2.OPProto.init(this);
          },
          setEngine: function(engine) {
            this.engine = engine;
          },
          start: function() {
            // Start engine.
          }
        });
      </mcs:script>
      
      <cx:client-class name="Car" start-method="start"/>
      
      <cx:reference name="engine" structural-relationship="child"
        component-types="car:Engine">
        <cx:client-reference setter="setEngine"/>
      </cx:reference>
      
      <cx:reference name="steeringWheel" structural-relationship="child"
        component-types="car:SteeringWheel">
        <cx:client-reference field="steeringWheel"/>
      </cx:reference>
      
      <cx:reference name="owner" structural-relationship="parent"
        component-types="car:Owner">
        <cx:client-reference property="owner"/>
      </cx:reference>
      
    </cx:component-class>
    
    <!--
     ! Engine class
     !
     ! An abstract class (no JavaScript implementation), that defines an API that other engines
     ! implementations have to follow. At the moment there is no way within the component class
     ! to define the API (in terms of methods, parameters, etc. However, future enhancements
     ! may add that support.
     !-->
    <cx:component-class name="car:Engine" defines="reference-types"/>
    
    <!--
     ! Diesel Engine class
     !
     ! A concrete implementation of an engine.
     !-->
    <cx:component-class name="car:DieselEngine" implements="car:Engine"
      defines="reference-types" id="Diesel">
      <mcs:script type="text/javascript">
        // ==================================================
        // JavaScript representation of Diesel Engine
        // ==================================================
        var DieselEngine = V$.Class.create();
        DieselEngine.methods({
          initialize: function(name) {
            this.name = name;
          }
        });
      </mcs:script>
    </cx:component-class>
    
    <!--
     ! Steering Wheel Class
     !
     ! A concrete implementation of a steering wheel.
     !-->
    <cx:component-class name="car:SteeringWheel" defines="reference-types" id="SteeringWheel">
      <mcs:script type="text/javascript">
        // ==================================================
        // JavaScript representation of Steering Wheel
        // ==================================================
        var SteeringWheel = V$.Class.create();
        SteeringWheel.methods({
          initialize: function(color, texture) {
            this.color = color;
            this.texture = texture;
          }
        });
      </mcs:script>
    </cx:component-class>
    
    <!--
     ! Car Owner Class
     !
     ! A concrete implementation of a car owner.
     !-->
    <cx:component-class name="car:Owner" defines="reference-types">
      <mcs:script type="text/javascript">
        // ==================================================
        // JavaScript implementation of Owner
        // ==================================================
        var Owner = V$.Class.create();
        Owner.mixin(V$.cf2.OPSet);
        V$.cf2.OPProto.add(Owner, "car", {});
        V$.cf2.OPProto.add(Owner, "name", {});
        Owner.methods({
          initialize: function(name) {
            V$.cf2.OPProto.init(this);
            this.setName(name);
          }
        });
      </mcs:script>
    </cx:component-class>
    
  </head>
  <body>
    
    <!--
     ! Steering Wheel Instance
     !-->
    <cx:component component-id="PinkFluffySteering" class-ref="SteeringWheel">
      
      <!--
       ! Must specify in each component instance how to construct a steering wheel as no
       ! name was specified on the cx:client-class element.
       !-->
      <cx:client-create>
        return new SteeringWheel("pink", "fluffy");
      </cx:client-create>
    </cx:component>
    
    <!--
     ! Engine instance
     !-->
    <cx:component component-id="Zetec" class-ref="Diesel">
      
      <!--
       ! Must specify in each component instance how to construct a diesel engine as no
       ! name was specified on the cx:client-class element.
       !-->
      <cx:client-create>
        return new DieselEngine("zetec");
      </cx:client-create>
    </cx:component>
    
    <!--
     ! Poor refers to how much money the driver has to spend on cars, not the quality of
     ! their driving. A poor driver is one that can only have at most a single car.
     !-->
    <cx:component id="PoorDriver">
      
      <!--
       ! An anonymous (no name, no id) class.
       !
       ! The encapsulating component does not specify class-ref attribute so it is bound to
       ! this class.
       !-->
      <cx:component-class defines="reference-types" implements="car:Owner">
        
        <!--
         ! Car references are optional - due to min-occurs = 0
         !-->
        <cx:reference name="car" structural-relationship="child" component-types="car:Car"
          min-occurs="0">
          <cx:client-reference setter="setCar"/>
        </cx:reference>
      </cx:component-class>
      
      <cx:client-create>
        // Create the client side representation of a poor driver.
        return new Owner("Willy");
      </cx:client-create>
      
      
      <cx:component id="CompanyCar" class-ref="Car">
        <cx:ref name="engine" component="Zetec"/>
        <cx:ref name="steeringWheel" component="PinkFluffySteering"/>
        <!--
         ! Owner is implicitly bound to containing component. 
         !-->
        
        <cx:client-start>
          // Make sure that the car owner name is appropriate to the steering wheel.
          c.setOwner('Shirley');
        </cx:client-start>
      </cx:component>
      
    </cx:component>
    
    <div>
      <cst:value property-value="PoorDriver#name" path="."/> has a
      <cst:value property-value="PoorDriver#car" path="steeringWheel.color"/>
      <cst:value property-value="PoorDriver#car" path="steeringWheel.texture"/>
      steering wheel and a <cst:value property-value="PoorDriver#car" path="engine.name"/> engine!
      <div>
        <ui:button>
          <cf2:on event="cf2:activate" set="PoorDriver#name" string="Fred"/>
          Rename to Fred
        </ui:button>
      </div>
    </div>
    
  </body>
</html>

Related topics