title: Override Multivalue component in Adobe CQ
body: <p>I am currently working on a project where i will need to implement custom multifield component. I am really specific about the fact that i need to create nodes (which can be any number) when user specifies a value instead of key, value property.</p>
  
  <p>I have currently added a pathField and a textbox.. which will be loaded using HTTP GET and when the user tries to input a value i would HTTP post from my custom extjs.</p>
  
  <p><img src="https://i.stack.imgur.com/ceyYp.png" alt="enter image description here"></p>
  
  <p>As shown above i would prefer the LHS to store entered values in nodes instead of RHS.
  I have created the component of the following structure</p>
  
  <p>As i'm going to make http calls and will not insert to jcr:content or any other path i've decided to remove the node reference "./multishort" below?</p>
  
  <p><img src="https://i.stack.imgur.com/8656z.png" alt="enter image description here"></p>
  
  <p>But when i do that the component loads but doesnt load the node properties. Can anyone suggest me how to handle this kind of loading nodes instead of properties?</p>
  
  <p>Please see the sample js file below. Note: it doesnt have details to post yet i havent included since i was not sure where it has to be instantiated. </p>
  
  <pre><code>/**
   * @class Ejst.CustomWidget
   * @extends CQ.form.CompositeField
   * This is a custom widget based on {@link CQ.form.CompositeField}.
   * @constructor
   * Creates a new CustomWidget.
   * @param {Object} config The config object
   */
  Ejst.CustomWidget = CQ.Ext.extend(CQ.form.CompositeField, {
  
      /**
       * @private
       * @type CQ.Ext.form.TextField
       */
      hiddenField: null,
  
      /**
       * @private
       * @type CQ.Ext.form.ComboBox
       */
      allowField: null,
  
      /**
       * @private
       * @type CQ.Ext.form.ComboBox
       */
      allowField2: null,
  
      /**
       * @private
       * @type CQ.Ext.form.TextField
       */
      otherField: null,
      /**
       * @private
       * @type CQ.Ext.form.TextField
       */
      shortField: null,
      /**
       * @private
       * @type CQ.Ext.form.TextField
       */
      mediumField: null,
      /**
       * @private
       * @type CQ.Ext.form.TextField
       */
      longField: null,
  
      /**
      * @private
      * @type CQ.Ext.form.TextField
      */
      linkURL: null,
  
  
      context1: null,
  
      price1: null,
  
  
  
      constructor: function(config) {
  
          config = config || { };
          var defaults = {
              "border": false,
              "layout": "table",
              "columns":2
          };
          config = CQ.Util.applyDefaults(config, defaults);
          Ejst.CustomWidget.superclass.constructor.call(this, config);
      },
  
      // overriding CQ.Ext.Component#initComponent
      initComponent: function() {
                  alert("initComponent")
          Ejst.CustomWidget.superclass.initComponent.call(this);
             alert("after super initComponent")
  
          this.hiddenField = new CQ.Ext.form.Hidden({
  
              name: this.name
          });
          this.add(this.hiddenField);
  
  
          this.allowField = new CQ.form.Selection({
  
  
  
              type:"select",
              cls:"ejst-customwidget-1",
              listeners: {
                  selectionchanged: {
                      scope:this,
                      fn: this.updateHidden
                  }
              },
              optionsProvider: this.optionsProvider
              // optionsProvider:[{text:"en",value:"en"},{text:"fr",value:"fr"}]
          });
          this.add(this.allowField);
  
  
          //this is for test pathfield
          this.allowField2 = new CQ.form.PathField({
  
              type:"select",
              cls:"ejst-customwidget-2",
              listeners: {
                  change: {
                      scope:this,
                      fn: this.updateHidden
                  }
              },
  
  
              optionsProvider: this.optionsProvider
               //optionsProvider:[{text:"en",value:"en"},{text:"fr",value:"fr"}]
          });
          this.add(this.allowField2);
  
  
          this.otherField = new CQ.Ext.form.TextField({
  
              cls:"ejst-customwidget-3",
  
              listeners: {
                  change: {
                      scope:this,
                      fn:this.updateHidden
                  }
              }
          });
          this.add(this.otherField);
  
      },
  
      // overriding CQ.form.CompositeField#processPath
      processPath: function(path) {
          alert("processPath")
          console.log("CustomWidget#processPath", path);
          this.allowField.processPath(path);
          this.allowField2.processPath(path);
      },
  
      // overriding CQ.form.CompositeField#processRecord
      processRecord: function(record, path) {
          alert("processRecord")
          console.log("CustomWidget#processRecord", path, record);
          this.allowField.processRecord(record, path);
          this.allowField2.processRecord(record, path);
      },
  
      // overriding CQ.form.CompositeField#setValue
      setValue: function(value) {
  
          alert("value ==&gt;&gt; "+value)
  
  
          //alert("setValue"+parts[0]+" = "+parts[1]+" = "+parts[2]+ " = "+parts[3]+" = "+parts[4])
  
  var currentPath = window.location.pathname+window.location.search;
              var curl = currentPath.split('.html');
              var suppressForbiddenCheck = true;
                      alert(curl[0])
              CQ.shared.HTTP.get(curl[0]+'/jcr:content/context-price.3.json', 
              function(options, success, response) {
                //  console.log(options); // Request options
                  //console.log(success); // true/false
                  //console.log(response); // Response obj
  
  
                  if(response.body != null){
                      console.log("json data ======&gt;&gt; "+response.body)
                      var json = JSON.parse(response.body);
  
                      var key, val, context, count = 0;
                      var stringified;
                      for(key in json.context){
                        if(json.context.hasOwnProperty(key)) {
                          console.log("key - "+key+" ,value - "+json.context[key])
                           // stringified = JSON.stringify(key);
                              val = json.context[key];
                                  //this.context1.set
                               // console.log("stringified --&gt;&gt; "+value+" == "+stringified) 
                                console.log(key + " : " + val)
  
                                  for(context in val){
                                    if(val.hasOwnProperty(context)) {
                                        var temp = context;
                                        if(temp.indexOf("price") != -1) {
                                           // this.price1 = val[context];
  
                                              this.otherField.setValue(val[context]);
                                             console.log(context+"------------"+this.price1)
                                        }
  
                                            if(temp.indexOf("context") != -1){
                                             //  this.context1 = val[context];
  
                                                  this.allowField2.setValue(val[context]);
                                               console.log(context+"------------"+this.context1)
                                            }
  
                                    }
                                  }
  
                            //}
  
                          count++;
                        }
                      }
                 //      console.log("logging-- "+ count)
  
                  }
  
                  if(success) {
                      // eval turns JSON response to JS Obj
                     // var myPage = CQ.shared.HTTP.eval(response);
                      //console.log(myPage['jcr:primaryType'])
                   //   console.log('url success ==&gt;&gt; '+response.body)
                  }else{
                     // console.log('falied to get url')
                  }
              }, this, suppressForbiddenCheck);
          var parts = value.split("/");
              //this.allowField.setValue(parts[0]);
              //this.allowField2.setValue(parts[1]);
              //this.otherField.setValue(parts[2]);
              this.allowField.setValue("fr");
              //this.allowField2.setValue(parts[0]);
              //this.otherField.setValue(parts[1]);
              this.hiddenField.setValue(value);
      },
  
      // overriding CQ.form.CompositeField#getValue
      getValue: function() {
          alert("getValue")
          return this.getRawValue();
      },
  
      // overriding CQ.form.CompositeField#getRawValue
      getRawValue: function() {
          alert("getRawValue")
  
  
          if (!this.allowField) {
              return null;
          }
  
          if (!this.allowField2) {
              return null;
          }
  
         // return (this.context1 + "/" + this.price1);
  
      return (this.allowField.getValue() + "/" + 
      this.allowField2.getValue()+ "/" +this.otherField.getValue() + "/" 
      +this.price1 + "/" + this.context1);
          },
  
               //private
      updateHidden: function() {
      alert("updateHidden")
      this.hiddenField.setValue(this.getValue());
          }
      });
  
  // register xtype
  CQ.Ext.reg('testfield', Ejst.CustomWidget);
  </code></pre>
  
  <p>Thanks in advance</p>