2015-03-11 4 views
3

Я пытаюсь создать компонент в AEM CQ5, который будет генерировать модуль викторины. Мое требование - создать диалог, который позволит мне создавать несколько вопросов, каждый из которых имеет несколько ответов. Мой диалог XML выглядит следующим образом -AEM CQ5 - Multifield custom xtype внутри пользовательского типа mutlifield xtype

<?xml version="1.0" encoding="UTF-8"?> 
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" 
    jcr:primaryType="cq:Dialog" 
    xtype="dialog"> 
    <items jcr:primaryType="cq:Widget" 
     xtype="tabpanel"> 
     <items jcr:primaryType="cq:WidgetCollection"> 
      <categories 
       jcr:primaryType="cq:Panel" 
       title="Questions & Answers"> 
       <items jcr:primaryType="cq:WidgetCollection"> 
        <questions-answers 
         jcr:primaryType="cq:Widget" 
         title="Questions & Answers" 
         name="./qasegment" 
         xtype="dialogfieldset"> 
          <items jcr:primaryType="cq:WidgetCollection"> 
           <link 
            jcr:primaryType="cq:Widget" 
            fieldDescription="Click on Add item to add questions. Once question is added, click on Edit Answers to add answers and the destination URLs" 
            name="./questionsAnswers" 
            typeHint="String" 
            xtype="multifield">       
            <fieldConfig 
             jcr:primaryType="nt:unstructured" 
             xtype="widgets.configurableQandAfield"/> 
           </link> 
          </items> 
        </questions-answers> 
       </items>  
      </categories> 
     </items> 
    </items> 
</jcr:root> 

С и xtype: mutlifield, я имею в виду пользовательский ExtJS виджет, который следующим образом. Это создаст (вопрос + вопрос конфигурации + Добавить ответ multifield) multifield.

NirmalWeb.ConfigurableQandAField = CQ.Ext.extend(CQ.form.CompositeField, { 

    /** 
    * @private 
    * @type CQ.Ext.form.HiddenField 
    */ 
    hiddenField: null, 

    /** 
    * @private 
    * @type CQ.Ext.form.TextField 
    */ 
    questionField: null, 

    /** 
    * @private 
    * @type CQ.Ext.form.TextField 
    */ 
    linkField: null, 

    textField:null, 

    answerOptions:null, 

    answerType:null, 

    widgetConfig: null, 


    constructor: function(config) { 
     config = config || { }; 
     var defaults = { 
      "border": true, 
      "layout": "form", 
      "labelSeparator": ":", 
      "padding": "10px" 
     }; 
     this.widgetConfig = config; 
     config = CQ.Util.applyDefaults(config, defaults); 
     EeWeb.ConfigurableQandAField.superclass.constructor.call(this, config); 
    }, 

    // overriding CQ.Ext.Component#initComponent 
    initComponent: function() { 
     EeWeb.ConfigurableQandAField.superclass.initComponent.call(this); 

     // Add a hidden field to hold our result to store. 
     this.hiddenField = new CQ.Ext.form.Hidden({ 
      name: this.name 
     }); 
     this.add(this.hiddenField); 


     // Add the link text field and label. 
     this.questionField = new CQ.Ext.form.TextField({ 
      fieldLabel: 'Question', 
      allowBlank: false, 
      emptyText: "Enter the question", 
      width: 500, 
      listeners: { 
       change: { 
        fn:this.updateQuestionStore 
       },  
       dialogclose: { 
        scope: this, 
        fn: this.updateHidden 
       } 
      } 
     }); 
     this.add(this.questionField); 

     var fieldsetConfig = CQ.Ext.apply({}, { 
      xtype: 'fieldset', 
      title: 'Edit Answer', 
      // title or checkboxToggle creates fieldset header 
      columnWidth: 0.5, 
      checkboxToggle: true, 
      collapsed: true, 
      items :[ 
       {  
       xtype: "fieldset", 
       title: 'Answer configurations', 
       autoHeight:true, 
       items: [ 
         new CQ.Ext.form.RadioGroup({ 
           vertical: false, 
           id:"answerType", 
           items: [ 
            {boxLabel: 'Text Answer', name: 'answerType', inputValue: 1, checked:true}, 
            {boxLabel: 'Image Answer', name: 'answerType', inputValue: 2} 
           ]  

         }), 
         new CQ.Ext.form.RadioGroup({ 
           vertical: false, 
           id:"answerOptions", 
           items: [ 
            {boxLabel: 'Single Answer', name: 'answerOptions', inputValue: 1, checked:true}, 
            {boxLabel: 'Multiple Answer', name: 'answerOptions', inputValue: 2} 
           ]  

         }), 
         ] 
       }, 
       { 
       xtype: "multifield", 
        fieldConfig : { 
         items: [ 
          { 
           xtype: "widgets.configurablemultiAnswerfield", 
           hideLabel: true, 
          } 
         ] 
        } 
       }, 
      ] 
     }); 
     this.textField = new CQ.Ext.form.FieldSet(fieldsetConfig); 
     this.add(this.textField); 

    }, 

    // overriding CQ.form.CompositeField#processInit 
    processInit: function (path, record) { 
     this.linkTextField.processInit(path, record); 
     this.linkField.processInit(path, record); 
    }, 

    // overriding CQ.form.CompositeField#setValue 
    setValue: function(value) { 
     var link = JSON.parse(value); 
     this.linkTextField.setValue(link.text); 
     this.linkField.show(); 
     this.hiddenField.setValue(value); 
    }, 

    // overriding CQ.form.CompositeField#getValue 
    getValue: function() { 
     return this.getRawValue(); 
    }, 

    // overriding CQ.form.CompositeField#getRawValue 
    getRawValue: function() { 
     return JSON.stringify("test"); 
    }, 

    // private 
    updateHidden: function() { 
     this.hiddenField.setValue(this.getValue()); 
    }, 

    editAnswer: function(value) { 
       alert("radio group change"); 
    } 

}); 

// Register our new xtype. 
CQ.Ext.reg('widgets.configurableQandAfield', NirmalWeb.ConfigurableQandAField); 

В пользовательском виджете, я создаю еще один многопрофильный для добавления текста ответа и наконечника инструмента, который является другим пользовательским виджетом. К сожалению, элемент multifield Add просто добавляет текстовое поле, а не все поля в настраиваемом виджетах 'configurablemultiAnswerfield'.

Пожалуйста, помогите мне. Дайте мне знать, если потребуется больше. Заранее спасибо.

+3

Только предложение, почему вы хотите, чтобы загромождать диалог с несколькими несколькими полями. Скорее вы можете задать вопрос с вопросом и мультифиллом для ответов. Перетащите компонент несколько раз на страницу и используйте его (что-то вроде вашего компонента формы по умолчанию, состоящего из нескольких полей ввода). – rakhi4110

+0

Спасибо rakhi за предложение. Конечной целью этого компонента викторины является повышение полезности страниц справки. Вместо того, чтобы показывать полный контент для всех клиентов, мы планируем показать клиентам соответствующий контент, задавая вопросы. Например, справочную страницу для планов данных Airtel - мы зададим вопрос 1 - какой пользователь вы a1. предоплата a2. pospaid. При выборе предоплаты он может либо привести к следующему вопросу, либо текстовому контенту и аналогичным образом для постплатежа. Абсолютно открыт для любых предложений по реализации этой логики. –

+1

Подход rakhi - это то, как я пойду, таким образом +1. Что касается вашей дальнейшей потребности, вы можете создать еще один компонент, который будет действовать как контейнер для вопросов, где вы могли бы реализовать логику, что будет отображаться дальше, в зависимости от результата предыдущего вопроса. – Thomas

ответ

1

Спасибо всем за ответы и предложения. Я смог исправить проблему с помощью приведенного ниже кода. Его маленький уродливый, но он выполняет эту работу.

  1. Решение, вызвавшее второй тип xtype, было легким. Я называл это неправильным. Это должно быть просто fieldConfig: {xtype: "widgets.configurableAnswer"} Чтобы заполнить для будущей ссылки, я столкнулся с еще одной проблемой - получить данные со второго xtype и отправить его обратно как JSON.Я изменил второй xtype метод updateHidden ниже

    updateHidden: function() { 
        this.hiddenField.setValue(this.getValue()); 
        this.findParentByType('widgets.configurableQandAfield').callUpdate(); 
    

    }

Вызов метод обновления в родительском xtype, как показано ниже:

callUpdate: function() { 
    this.hiddenField.setValue(this.getValue()); 
}, 

Чтобы сохранить данные второго xtype из первый xtype Я использовал приведенный ниже код в методе значения getRaw

getRawValue: function() { 
    var link = { 
     "questionText": this.questionText.getValue(), 
     "answerStack" : this.answerSet.findByType('multifield')[0].getValue(), 
     }; 
    return JSON.stringify(link); 
}, 

Прикрепление первого Xtype JS для дальнейшего использования.

Nirmalweb.ConfigurableQandAField = CQ.Ext.extend(CQ.form.CompositeField, { 

/** 
* @private 
* @type CQ.Ext.form.HiddenField 
*/ 
hiddenField: null, 

/** 
* @private 
* @type CQ.Ext.form.TextField 
*/ 
questionText: null, 

/** 
* @private 
* @type CQ.Ext.form.FieldSet 
*/ 
answerSet:null, 

constructor: function(config) { 
    config = config || { }; 
    var defaults = { 
     "border": true, 
     "layout": "form", 
     "labelSeparator": ":", 
     "padding": "10px" 
    }; 
    config = CQ.Util.applyDefaults(config, defaults); 
    Nirmalweb.ConfigurableQandAField.superclass.constructor.call(this, config); 
}, 

// overriding CQ.Ext.Component#initComponent 
initComponent: function() { 
    Nirmalweb.ConfigurableQandAField.superclass.initComponent.call(this); 

    // Add a hidden field to hold our result to store. 
    this.hiddenField = new CQ.Ext.form.Hidden({ 
     name: this.name 
    }); 
    this.add(this.hiddenField); 

    // Add the link text field and label. 
    this.questionText = new CQ.Ext.form.TextField({ 
     fieldLabel: 'Question', 
     cls:"ee-configurableqandafield-text", 
     allowBlank: false, 
     emptyText: "Enter the question", 
     listeners: { 
      change: { 
       scope:this, 
       fn:this.updateHidden, 
       fn:this.questionBank 
      },  
      dialogclose: { 
       scope: this, 
       fn: this.updateHidden 
      } 
     }, 
     width: 500, 
    }); 
    this.add(this.questionText); 

    var fieldsetConfig = CQ.Ext.apply({}, { 
     xtype: 'fieldset', 
     title: 'Add Answers', 
     // title or checkboxToggle creates fieldset header 
     columnWidth: 0.5, 
     checkboxToggle: true, 
     collapsed: true, 
     items :[ 
      { 
      xtype: "fieldset", 
      title: 'Answer configurations', 
      autoHeight:true, 
      items: [ 
        { 
         xtype: "selection", 
         type:"select", 
         fieldLabel:'Answer Type', 
         listeners: { 
          change: { 
           scope:this, 
           fn:this.updateHidden, 
          },  
          dialogclose: { 
           scope: this, 
           fn: this.updateHidden, 
          }, 
          selectionchanged :{ 
           scope:this, 
           fn:this.updateHiddenAnsType 
          } 
         }, 
         options:[ 
          { value:"text",text:"Text Answer"}, 
          { value:"image",text:"Image Answer"} 
         ] 
        }, 
        { 
         xtype: "selection", 
         type:"select", 
         fieldLabel:'Answer Options', 
         listeners: { 
          change: { 
           scope:this, 
           fn:this.updateHidden 
          },  
          dialogclose: { 
           scope: this, 
           fn: this.updateHidden 
          } 
         }, 
         options:[ 
          { value:"single",text:"Single Answer"}, 
          { value:"multi",text:"Multiple Answer"} 
         ] 
        }, 
        ] 
      }, 
      { 
       xtype: "multifield", 
       addItemLabel:"Add an answer", 
       listeners: { 
        change: { 
         scope:this, 
         fn:this.updateHidden 
        },  
        dialogclose: { 
         scope: this, 
         fn: this.updateHidden 
        } 
       }, 
       fieldConfig : { 
        xtype: "widgets.configurableAnswer", 
       } 
      }, 
     ] 
    }); 
    this.answerSet = new CQ.Ext.form.FieldSet(fieldsetConfig); 
    this.add(this.answerSet); 


}, 

// overriding CQ.form.CompositeField#processInit 
processInit: function (path, record) { 
    this.questionText.processInit(path, record); 
    this.answerSet.processInit(path, record); 
}, 

// overriding CQ.form.CompositeField#setValue 
setValue: function(value) { 
    var link = JSON.parse(value); 
    this.questionText.setValue(link.questionText); 
    this.answerSet.setValue(link.answerStack); 
    this.hiddenField.setValue(value); 
}, 

// overriding CQ.form.CompositeField#getValue 
getValue: function() { 
    return this.getRawValue(); 
}, 

// overriding CQ.form.CompositeField#getRawValue 
getRawValue: function() { 
    var link = { 
     "questionText": this.questionText.getValue(), 
     "answerStack" : this.answerSet.findByType('multifield')[0].getValue(), 
     }; 
    return JSON.stringify(link); 
}, 

// private 
updateHidden: function() { 
    this.hiddenField.setValue(this.getValue()); 
}, 

callUpdate: function() { 
    this.hiddenField.setValue(this.getValue()); 
}, 

}); 
// Register our new xtype. 
CQ.Ext.reg('widgets.configurableQandAfield', Nirmalweb.ConfigurableQandAField); 

в результате JSON будет, как показано ниже:

{ 
"questionText": "What type of user are you?", 
"answerStack": [ 
    "{\"answerText\":\"a1\",\"answerStyle\":\"questionStyle\",\"answerToolTip\":\"t1\",\"destinationType\":\"text\",\"destinationTextCTA\":\"Fill in the Unlock form\",\"destinationTextCTAURL\":\"https://google.com\"}", 
    "{\"answerText\":\"a2\",\"answerStyle\":\"questionStyle\",\"answerToolTip\":\"t2\",\"destinationType\":\"text\",\"destinationTextCTA\":\"Fill in the Unlock form 2\",\"destinationTextCTAURL\":\"https://facebook.com\"}" 
] 

}

0

Я согласен с комментариями, говоря, что это было бы лучше иметь компонент контейнера вместо усложняя диалог, но если ваш еще ищете способ вытащить из многопрофильного в многопрофильном следующий подход должен помочь

You может создать эффект, используя три типа:

1) Multicomposite - xtype, который хранит каждую запись в виде дочернего узла с полями как свойствами. [Developed by Citytech inc]

2) Multifieldpanel - xtype, который хранит multifield как массив объектов json, где каждое поле является свойством объекта json. [Разработано в ACS]

3) Multifield - многоуровневый многотипный тип.

Диалог структуры (с помощью меню, как пример):

multicomposite (outer multifield) |-fieldConfigs |- field A (lets say a textfield , for the menu's coulmn name) |- field B (a pathfield to configure the link for the column name) |- field C (multifield , the inner multifield to hold sub menu entries) |-fieldConfig - xtype : multifieldpanel |- field Ca (textfield to hold title) |- field Cb (pathfield for the link)

это будет хранить данные в следующем формате:

{ 
jcr:primaryType: "nt:unstructured", 
menu: 
    { 
     jcr:primaryType: "nt:unstructured", 
     item_1: 
     { 
      submenu: 
      [ 
      "{"title":"Link 1","link":"http://stackoverflow.com"}", 
      "{"title":"Link 2","link":"http://stackoverflow.com"}" 
      ], 
      title: "Main Menu Item 1", 
      jcr:primaryType: "nt:unstructured", 
      link: "http://stackoverflow.com" 
     }, 
     item_2: 
     { 
      submenu: 
      [ 
      "{"title":"Sub menu 1","link":"http://stackoverflow.com"}", 
      "{"title":"Sub menu 2","link":"http://stackoverflow.com"}" 
      ], 
      title: "Main Menu item 2", 
      jcr:primaryType: "nt:unstructured", 
      link: "http://stackoverflow.com" 
     } 
    } 
} 

Вы можете найти подробную запись на этом методе в моем посте here

+0

Спасибо, спасибо за ваш ответ. Определенно ваш ответ помог мне дойти до моего ответа. Я обновил ответ, который я понял из-за проблемы. –

Смежные вопросы