Defines a reference from one component to another component.
Attribute | Description | Type | Default | Options | Use |
---|---|---|---|---|---|
component-types | The space-separated list of client-side types that the referenced component must implement. This is used to check that an explicit reference (by id) is to the correct type of component and to check for a structural reference to a component. If the set is empty, then it can reference any component. | xs:string | optional | ||
min-occurs | The minimum number of components that must be referenced by this reference. If the value of the attribute is set to '0', then a reference is optional. If it is set to '1', then a reference is required. If the attribute is set to '0', then it is the responsibility of the client-side implementation of the components to ensure that it works correctly when no reference is provided. In such a case, the server-side behavior will depend on the validation mode; the component class definition and the client-side behavior will depend on any custom JavaScript and component behavior. | xs:integer | 1 | 0, 1 | optional |
name | The name of the reference, also used as the name of the attribute on the component element to specify an explicit reference by id, and the observable property to hold the reference on the client-side. | xs:string | required | ||
structural-relationship | Defines the structural relationship between the component to which the reference point belongs and the component to which the reference point refers. The attribute supports the following values: 'parent' and 'child'. The value of 'parent' indicates that the reference must automatically be bound to the parent component if it implements all the specified types. The value of 'child' indicates that the reference must automatically be bound to a child component if it implements all the specified types. If not specified, then no implicit relationships are supported and therefore the reference must be explicitly set through some custom JavaScript on the client. | xs:string | child, parent | optional |
<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>