This translation is older than the original page and might be outdated.




In XOne there are three types of relations between collections:

TYPE OF RELATION VISUAL REPRESENTATION DESCRIPTION
Relation from 1 to 1 (Magnifying Glass) Used in relations with collectins that have many data.
Relation from 1 a 1 (Combo) Used in relations with collections with little data.
Relation from 1 to Several (Contents) Used when we don´t know the number of logs we can associate. A tipical example of contents are the Orders and its details.


This kind of relation is used to select a unique value from another collection.

In Database only will be saved the IDE of the selected row, being able to rescue, besides, just to show on screen, another fields of the selected row.


Link field view of magnifier type in Pocket PC
Link field view of magnifier type in BlackBerry
	<prop name="IDCLIENTE" group="1" type="N" visible="0" mapcol="Clientes" mapfld="ID"/>
	<!-- 
		Este campo es el que realmente SE GRABARÁ en la BD, normalmente no está visible.
		Enlaza con la colección "Clientes" y nos guardaremos el valor del campo "ID" seleccionado.
	-->
 
	<prop name="MAP_CLIENTE" ... linkedto="IDCLIENTE" linkedfield="NOMBRE" onchange="Refresh" value="##ID##">Cliente</prop>
	<prop name="MAP_CONTACTO" ... linkedto="IDCLIENTE" linkedfield="CONTACTO" locked="true" onchange="Refresh">Contacto</prop>
	<!-- 
		Estos campos están asociados con el campo "IDCLIENTE". Al llevar el prefijo "MAP_" NO se graban en BD.
		Para obtener sus valores utilizan el campo "IDCLIENTE" (linkedto) como enlace a la otra colección.
		El linkedfield es el campo que mostraremos por pantalla, el cual nos traemos de la otra colección.
		La lupa aparece en el campo que no está locked="true", para poder buscar directamente desde él.
		Los demás campos podemos ponerlos con el locked="true" para que NO se pueda editar su contenido NI TAMPOCO salga la lupa.
	-->


It is similar than the previous one, but it is used only when the collection called has little data.

This is important, because when the edition window is going to be painted, and one the fields has a combo, it will load in memory all the values that this combo can contain, so if there are many data to be loaded at the time to open that editing window, it may take a long time.


Link field view of magnifier type in Pocket PC
Link field view of magnifier type in BlackBerry

Example of Code

	<prop name="IDTIPO" group="1" type="N" visible="0" mapcol="Tiposvisitas" mapfld="ID"></prop>
		<!-- 
			Este campo es el que realmente SE GRABARA BD, normalmente no está visible.
			Enlaza con la colección "TiposVisitas" y nos guardaremos el valor del campo "ID" seleccionado.
		-->
 
	<prop name="MAP_TIPO" ... type="T" linkedto="IDTIPO" linkedfield="DESCRIPCION" showinline="true">Tipo</prop>
		<!-- 
			Este campo está asociado con el campo "IDTIPO". Al llevar el prefijo "MAP_" NO se graba en BD.
			Para obtener sus valores utiliza el campo "IDTIPO" como enlace a la otra colección.
			La diferencia con el control tipo "lupa" es el atributo showinline="true", que es realmente
			el que le da la apariencia de combo. 
		-->

The difference with the magnifier type is just the showinline=“true” attribute and besides the fact that the combo is loaded with values when entering in the collection unlike the magnifier.


The structure is similar than the previous ones, but it is used exclusively when the collection called has little data and clearly defined.
IT IS NOT executed a table in Database, the values are defined in a first PROP and are rescued in another PROP.

Example of Code


<prop name="MAP_IDTIPO" visible="0" group="1" type="N" mapcol-values="COMERCIAL,DPT INTRODUCCION,RESPONSABLE S EXT"/>
<!--
   Al ser un MAP_ no se graba en BD y el atributo mapcol-values define los valores posibles, separados por comas.
-->
<prop name="DESTINATARIO" labelwidth="0" type="T" size="40" onchange="Refresh" fieldsize="23" visible="1" showinline="true" group="1" linkedto="MAP_IDTIPO" linkedfield="DATA"/>
<!--
   Este campo es el que se graba en BD, el atributo linkedfield siempre vale DATA.
-->


A contents collection is a group of data that depend on a header, that is, a collection that depends on another.

It is used when we do not know the number of logs we are going to be able to associate in the header collection.

Tipical examples of contents are the orders and its details lines or items and its stocks.



Link field between the header and the details collection(contents)


To define collection with content it is necessary to follow several steps:


The main collection must be defined (e.g. documents collection). Each one of the properties defined in this collection correspond to the object header.

It is defined the content collection.

In the example we are using, a collection of document details will be created. Each one of the properties defined in this collection will correspond to the detail lines of the document.

In the main collection a content definition is included. The content definition has the following format:

    <prop name="@NombrePropiedad" group="NumeroGrupo" type="Z" contents="nombre del content"></prop>
    <contents name="nombre del content" src="coleccion" filter="sentencia WHERE"></contents>

prop

  • name: It assigns a name to the property. It is usual to put an “@” in front to indicate that is a property which makes reference to a content. We recommend its use to distinguish and locate easily within the mappings.
  • group: Group or tab where the content will appear.
  • type: Type of property. To refer to a content it has to be “Z”.
  • contents: Content name. This attribute makes a call to the contents node that has its same name. That is, the contents attribute has to be the same than the name of the contents node.
  • width: It defines the content width.
  • height: It defines the content height. In Android, is possible to modify this attribute by script. Let´s suppose that for instance you need a search box that is hidden and that you enables it with a button, and you want that everything takes always the 100% of the screen. So, what you would do would be the following:
    <prop name="MAP_TAMCONTENT" visible="0" frame="id1" group="1" type="T" size="30" title="Tamaño content" />
    <prop name="@MaquinasContent" frame="id4" group="1" type="Z" contents="MaquinasContent" width="100%" height="##FLD_MAP_TAMCONTENT##" onchange="Refresh" editmodal="true" forceonchange="true" mask="0" locked="true" />
    <contents name="MaquinasContent" src="MaquinasContent" filter="IDCLIENTE=##FLD_MAP_IDCLIENTE##" />
<before-edit>
    <action name="runscript">
        <script language="VBScript">
            this("MAP_TAMCONTENT")="75%"
        <script>
    </action>
<before-edit>

Now, through script you would modify the size whenever you want, in the same way.

contents

  • name: It assigns a name to the content. Every content must have a name, that must match with the contents attribute from the previous section.
  • src: It indicates the contents collection name. Whenever a container object is created, the source collection is copied and it is filled with those objects that belong to the container only. In the example we are putting (document with detail lines) the container object is the document (an object for each header log). Each container object has assigned several detail lines (in a linked table). The logs of the linked table are placed in the contents collection.
  • filter: It is the filter that indicates which logs of the linked table “belong” to that object in particular. If the details table is linked with the main table by the IDDOCUMENTO field, the filter would be something like IDDOCUMENTO=##ID##. The data components will be in charge to replace the ##ID## macro by the proprietary object for each one of the documents.


If what you want is to link the order with the details at the moment to save the order (father), the necessary actions are defined so that the necessary links are made during the saving of the order, so that the correct values ​​that determine the relation between the detail records and the order in the Database are stored in the tables.

The following codes have the sense to assign to the IDPEDIDO field of the details, the ID value of the order in the header collection, in such way that the records are linked. (relation header-details)


At the Orders collection (father)the following code would have to be added:

<insert>
  <!-- Al grabar un nuevo pedido en base de datos, a cada detalle se le pone el ID 
  del pedido creado -->
  <action name="link" coll="Detalles" field="IDPEDIDO" value="##ID##"></action>
</insert>


At the Details collection (content collection or daughter) the following code would have to be added:

<create>
    <!-- Al crear una nueva línea de Detalle, al IDPEDIDO de ese detalle se le pone 
      el ID del PEDIDO que estamos realizando -->
    <action name="setfldval" targetfld="IDPEDIDO" sourcefld="ID"></action>
</create>



Finally, we get the father-child structure as shown below:

Let´s suppose that we have two tables with the following definitions:

A) Orders

FIELD DESCRIPTION
ID Autonumeric identifier of the order
NUMBER Order number
IDCLIENT Client identifier
DATE Order date


B) Order details. For each order it will have one or several records in this table.

FIELD DESCRIPTION
ID Autonumeric identifier of the detail.
IDORDER Identifier of the father of this detail.
IDITEM Identifier of the item selected in this record.
AMOUNT Amount ordered of the item in question


Now, we are going to create a collections structure to manage these data in an application by using the definitions described in this section and in the previous one.

Firstly, we define the content collection ( although it does not have to be like that, since the collections may be defined in any order). The collection is defined as if it were to be used in an independent way.

In this case we would have the following definition:

<coll name="Detalles" title="Detalle pedido" sql="SELECT d.* FROM ##PREF##Detalles d" objname="Detalles" updateobj="Detalles" progid="ASData.CASBasicDataObj">
     <prop name="IDPEDIDO" group="1" visible="0" type="N" mapcol="Pedidos" mapfld="ID"></prop>
     <prop name="IDARTICULO" group="1" visible="0" type="N" mapcol="Articulos" mapfld="ID"></prop>
     <prop name="CANTIDAD" locked="true" visible="7" group="1" type="N2" fieldsize="12" size="12">Cantidad</prop>
     <create>
        <action name="setfldval" targetfld="IDPEDIDO" sourcefld="ID"></action>
     </create>
</coll>


Now we can define the main collection, and inside of it we include the contents mapping property.

The definition of the collection would be like this:

  <coll name="Pedidos" title="el Pedido" sql="SELECT p.* FROM ##PREF##Pedidos p" objname="Pedidos" updateobj="Pedidos" progid="ASData.CASBasicDataObj" loadall="false" withopen="false">
    <group name="General" id="1"></group>
    <group name="Detalles" id="2"></group>
       <prop name="IDCLIENTE" group="1" visible="0" type="N" mapcol="Clientes" mapfld="ID"></prop>
       <prop name="NUMERO" visible="3" group="1" type="N" fieldsize="12" size="12"></prop>
       <prop name="FECHA" visible="3" group="1" type="D" fieldsize="12" size="12"></prop>
       <prop name="MAP_CLIENTE" visible="3" group="1" type="T" fieldsize="12" size="12" linkedto="IDCLIENTE" linkedfield="NOMBRE"></prop>
       <prop name="@DETALLES" group="2" type="Z" contents="Detalles">Detalles</prop>
       <contents name="Detalles" src="Detalles" filter="IDPEDIDO=##ID##"></contents>
       <insert>
           <action name="link" coll="Detalles" field="IDPEDIDO" value="##ID##"></action>
       </insert>
  </coll>


It may be the case that a same collection may be used as content for more than a main collection, for instance, a documents details collection may be used both for the invoices and for the delivery notes.

In this case, those properties of the collection that refer to the proprietary must not reference a name, since there is no way to know in which of the possible containers objects the attribute is being evaluated.

For that reason it exists the ##OWNERCOLL## macro that is used to evaluate the mapcol attributes of those properties that refer to the proprietary collection.

The proprietary collection and content example that we show below illustrates the use of the ##OWNERCOLL## in a case as the mentioned before.

Firstly, let´s take the following definition of the details collection:

<coll name="Detalles" title="el detalle " .... otros atributos omitidos ... >
  <prop name="IDDOCUMENTO" group="1" type="N" visible="0" mapcol="##OWNERCOLL##" mapfld="ID"></prop>
  <otras propiedades omitidas>
</coll>


Now, let´s suppose that we have two collections of documents that use the collection previously defined:

<coll name="FacturasVentas" title="la factura de venta" ... otros atributos omitidos ...>
  <propiedades omitidas>
  <prop name="@DETALLES" type="Z" contents="Detalles" lines="8"></prop>
  <contents name="Detalles" src="Detalles" filter="IDDOCUMENTO=##ID##"></contents>
</coll>
 
<coll name="AlbaranesVentas" title="el albaran de venta" ... otros atributos omitidos ...>
  <propiedades omitidas>
  <prop name="@DETALLES" type="Z" contents="Detalles" lines="8"></prop>
<contents name="Detalles" src="Detalles" filter="IDDOCUMENTO=##ID##"></contents>
</coll>


In the code fragment shown above, it can be seen that the “Detalles” collection has been used as a collection of content both by the “FacturasVentas” collection and by “AlbaranesVentas”.
This means that in the definition of “Detalles” the IDDOCUMENT field refers indistinctly to one or another collection depending on which of them is the one that makes mention of that field.
Therefore it is necessary to indicate the macro ## OWNERCOLL ## that will be evaluated with the correct name for each of the details.
Thus, when the collection is requested to map the IDDOCUMENT field in the “Detalles” of “FacturasVentas”, the attribute will take the “FacturasVentas” value, and when it is requested in the “AlbaranesVentas” it will take the name of that collection.
This allows a single definition to define contained collections for many others, without the need to create copies of the same definition only because mapcol must have a unique value.

We have to take into account, that in the main collection, whenever there is a content it must carry a DELETE node with an EXECUTESQL action for when the father log is deleted, also delete the children logs.


disablevisible="condition"


If the condition is met, the content will be disabled.

Example:

  ...
  <contents name="Detalles" src="Detalles" filter="IDDOCUMENTO=##ID##" disablevisible="cliente=1"></contents>
  ...

disableedit="condition"


A condition is set. If this condition is met, it doesn´t let edit, if on the contrary it is false, it lets edit.

Example:

  ...
  <contents name="Detalles" src="Detalles" filter="IDDOCUMENTO=##ID##" disableedit="editar=1"></group>
  ...

mask="value"


This attribute works as a mask. Its function is given according its value:

- 1 → new.

- 2 → edit.

- 4 → delete.

- 8 → filter.

- 16 → exit.

The sum of some or all the values would give the different options.

 E.g.: for the value 27 we could make the operations of new, edit, filter and exit. (1+2+8+16=27).

edit_inline / forceonchange / editmodal =" true | false "

- edit_inline → It edits in line.

- forceonchange → It forces the refresh by returning from the previous window.

- editmodal → When double click it edits in another window.

Example:
This example, we make that the content is edited in another tab instead of being in it.

   ...
   <prop name="@DETALLESULTIMOS" visible="1" group="3" type="Z" contents="Detalles" 
     lines="9" edit_inline="false" editmodal="true" forceonchange="true" onchange="refresh"></prop>
   <contents name="Detalles" src="Detalles" filter="IDDOCUMENTO=##ID##"></contents>
   ...

For this, the forceonchange and editmodal attributes are set to true, while edit_inline to false.