Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Example of usage for SimpleType::setSimpleTypeValueUpdater

    Hello,

    I currently evaluating the 3.1d enterprise edition (2012/10/04) and try to define my own SimpleType to handle a complex object like this:

    Code:
     prices:{
                scales:[
                    {
                        amount:0, 
                        [b]price:10,[/b]
                    }
                ], 
            }
    I managed it, to extract the value via SimpleType::setSimpleTypeValueExtractor like this:
    Code:
    			setSimpleTypeValueExtractor(new SimpleTypeValueExtractor() {
    				@Override
    				public Object getAtomicValue(Object value) {
    					if (!(value instanceof Map)) return null;
    					List<Map> scales = (List) ((Map) value).get("scales");
    					if (scales == null){
    						return null;
    					}
    					for (Map scale : scales) {
    						if (((Number)scale.get("amount")).intValue() == 0){
    							return scale.get("price");
    						}
    					}
    					return null;
    				}
    			});
    but the method SimpleType::setSimpleTypeValueUpdater seems not to work like I expect. Currently I've tried to to this:
    Code:
    			setSimpleTypeValueUpdater(new SimpleTypeValueUpdater() {
    				@Override
    				public Object updateAtomicValue(Object atomicValue, Object currentValue) {
    					if (!(currentValue instanceof Map)) return null;
    					List<Map> scales = (List) ((Map) currentValue).get("scales");
    					if (scales == null){
    						return currentValue;
    					}
    					for (Map scale : scales) {
    						if (((Number)scale.get("amount")).intValue() == 0){
    							scale.put("price", Float.valueOf(atomicValue.toString()));
    						}
    					}
    					return currentValue;
    				}
    			});
    The data send back to the server is equals to the one I received via the fetch operation. Am I missing something?

    #2
    This is generally not the kind of thing you use SimpleType for - looks like you have a related complex object, so you should be using a related DataSource (via foreignKey) or a nested DataSource (via setFieldTypeAsDataSource).

    However if you have an actual use case for SimpleTypeValueUpdater (tends to be something like an atomic type where the store value is encoded into a String in some way), we would need runnable code to take a look at a problem.

    Comment


      #3
      I would like to implement the following:

      An item can have a price containing multiple price scales like this:

      Code:
      @Entity
      public class ItemEntity {
      
      	@Id
      	protected String uuid;
      
      	@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
      	private PriceEntity prices;
      
      	/* getter and setter */
      }
      Code:
      <DataSource ID="Item" serverType="hibernate" dropExtraFields="true" beanClassName="ItemEntity">
          <fields>
              <field name="uuid" type="text" primaryKey="true" autoGenerated="true"/>
              <field name="prices" type="Price" required="false"  canEdit="true" foreignKey="Price.priceId"/>
          </fields>
      </DataSource>
      Code:
      @Entity
      public class PriceEntity {
      	@Id
      	private String priceId;
      
      	@OneToMany(mappedBy = "container", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
      	private List<PriceScaleEntity> scales;
      
      	/* getter and setter */
      }
      Code:
      <DataSource ID="Price" serverType="hibernate" dropExtraFields="true" beanClassName="PriceEntity">
           <fields>
              <field name="priceId" type="text" primaryKey="true" autoGenerated="true"/>
              <field name="scales" type="PriceScale" foreignKey="PriceScale.uuid" multiple="true"/>
          </fields>
      </DataSource>
      Code:
      @Entity
      public class PriceScaleEntity {
      
      	@Id
      	private String uuid;
      
      	@ManyToOne
      	private PriceEntity container;
      
      	private int amount;
      
      	private float price;
      	
      	/* getter and setter */
      }
      Code:
      <DataSource ID="PriceScale" serverType="hibernate" dropExtraFields="true" beanClassName="PriceScaleEntity">
           <fields>
              <field name="uuid" type="text" primaryKey="true" autoGenerated="true"/>
              <field name="container" foreignKey="Price.priceId"/>
              <field name="amount" type="INTEGER"/>
              <field name="price" type="FLOAT"/>
          </fields>
      </DataSource>
      Now I want a ListGrid where ou can edit the default price (this is the price where the amount == 0) of all items. Additionally I want to display an icon right to the price enabling the user to open an editor window where he can edit (add / update/ remove) all the scales. In this editor he can also change the value of the default price, so it would be nice if both editors use the same record as data base. This is why I try to use the SimpleType to get the default price of the price record.
      Maybe you can point me to a better approach to solve this problem with SmartGwt.
      Last edited by andy.2003; 8 Oct 2012, 11:30.

      Comment


        #4
        You have a DataSource for the Price records already - you can bind this to a ListGrid and fetch Price records, and if you prefer to hide the "scale" field and edit it via an icon, you can do that by adding a FormItemIcon to the editorType for the price field that launches your picker, and have the picker call setEditValue() on the "scale" field with whatever the user chooses.

        Comment


          #5
          And is there a way to have a default price be shown in the ListGrid of Items? I don't want to load each price separately by a nested ListGrid. There should be one fetch of all Items including the complex structure for prices and scales (the fetch already works as expected).
          There shouldn't be an own ListGrid for the price! Only one ListGrid for the Item and one for the Scales shown by triggering the icon.

          The JavaDoc for SimpleType says:
          ... The SimpleType class also allows data to be stored in some opaque format but treated as simple atomic values as far as Smart GWT components are concerned by implementing SimpleType.getAtomicValue and SimpleType.updateAtomicValue methods. For example, if some record has a field value set to a javascript object with the following properties:

          { stringValue:"A String", length: 9 }

          this value could be treated as a simple string by defining a SimpleType with inheritsFrom set to "text" and a custom getAtomicValue() method that simply extracted the "stringValue" attribute from the data object. DataBoundComponents would then display the string value, and use it for sorting and other standard databinding features. ...
          which is exactly what I want. I have a complex JavascriptObject as value and want to extract an atomic value for editing it in the Item-ListGrid (this also works in my case). The only thing which doesn't work is to get the edited value back into the complex object structure for saving.

          Comment


            #6
            At this point, we can't really tell what UI you have in mind or how it relates to your data, but it certainly doesn't sound like a use case for SimpleType.

            As a general tip, never use SimpleType if you want to edit *multiple* aspects of the value. That seems to be the case here, which is why we recommend a separate Record.

            Only use SimpleType when you have a value that is logically a singular value, and appears in the UI as a singular value, but is simply stored in way that is not a normal atomic type (String, Number, Date).

            Comment


              #7
              At the end there is the simple question: Is there a way to edit a single attribute of a complex type in a TextItem and store the edited value back to the complex structure?

              Comment


                #8
                Yes of course, ListGrid editing does this.

                But you seem to want something more since, when we mentioned this, you started talking about nested grids.

                Comment


                  #9
                  Thank you for your support and advice. I solved the problem finally like this:

                  1. I created an own PriceItem extending the TextItem
                  1.1. I customized the setEditorValueFormatter and setEditorValueParser to Handle the complex structure (I had to use GWT overlay types)
                  1.2. set setFetchMissingValues(false); so that the Prices are not fetched a second time
                  1.3. use setIcons to add a icon for opening the ScaleEditor

                  2. The ScaleEditor is a Listgrid with Local storage working with the complex structure of the price. It is shown in a Window.

                  3. Using this PriceItem in a ListGritItem via setEditorType(priceItem) + adding a custom CellFormatter to display the default price in a Grid

                  4. on the server side I used DMI to handle the complex price structure for adding and updating the Object which contains the price.

                  Comment

                  Working...
                  X