# Components

PForm - Should be the top level component for the form. Handles form initialization and validation. Example:

<PForm>
  <VRow>
    <VCol>
      <ZeroInformation :accountName="params.account.Name" :accountId="params.account.Id" showAccountAddress />
    </VCol>
  </VRow>

  <VRow>
    <VCol cols="6">
      <CallChannels v-model="callChannel" :callChannels="callChannels" />
    </VCol>
    <VCol cols="6">
      <CallFocus />
    </VCol>
  </VRow>

  <VRow v-if="!config.noNotes">
    <VCol>
      <FormTextarea :defaultValue="params.notes" title="Pre-Call Notes" submissionParam="preCallNotes" />
    </VCol>
  </VRow>
</PForm>

PArrayFormField - There are some fields that require addition/removal in almost every postcall (most generic example is Follow Ups). This component aims to extract the common logic of item addition/removal to the field. It accepts an array as a v-model to handle item add-remove operations and an array for the fields. The fields array can be an array of strings describing the fields of each item or an object with fields name and defaultValue if the fields need a default value.

The component renders a default slot with providing each item as a slot prop.

<PArrayFormField v-model="items" :fields="['discussionItem', 'reaction']">
  <template #default="{ item }">
    <div class="d-flex">
      <VAutocomplete
        v-model="item.discussionItem"
        v-bind="selectPropsGetter()"
        :items="selectableCallKeyMessageItems"
        :multiple="false"
        class="mr-3"
      />
      <VSelect
        v-model="item.reaction"
        v-bind="selectPropsGetter()"
        :returnObject="false"
        :items="REACTIONS"
        :multiple="false"
      />
    </div>
  </template>
</PArrayFormField>

PFormItem is a higher order component to make developing straightforward form fields straightforward. It accepts props to be used as a form field when getParamsForSubmission is called. Those are:

  • title: the field's title to be rendered on the form
  • submissionParam: the parameter to be added to the getParamsForSubmissions return JSON. Required if parser is not given.
  • defaultValue?: default value of the field (if any)
  • validator?: function to be used to validate the field when canSubmit gets called. Returning false from the function will prevent form from submitting.
  • required?: mark the field as required, this also makes the field checked if it has value when canSubmit gets called
  • parser?: a function to parse the data to send to getParamsForSubmission. Required if submissionParam is not given.
  • id?: a unique id for the field. Required if submissionParam is not provided.
  • precallField?: field to prefill the data from precallJSON.
  • precallServerField?: when multiple platform support or SFDC call editing support is needed this field should be provided.
  • serverDataParser?: data for precallServerField comes in a way that requires parsing before using properly. This function is used to parse the data, can be async.

It also accepts an optional v-model if the developer wants to have control over the selected value of the form field.

The PFormItem component renders a slot with providing the v-model value as a slot prop - so that developer can render any kind of form control inside the FormItem.

<PFormItem
  :title="$t('My form field')"
  submissionParam="myFormField"
>
  <template #default="{ value, updateValue }">
     <VInput :value="value" @change="updateValue($event)" />
  </template>
</FormItem>

<!-- with v-model -->
<PFormItem
  :title="$t('My form field')"
  submissionParam="myFormField"
  v-model="value"
>
  <VInput v-model="value" />
</PFormItem>
  • There are some components that are derived from PFormItem. They are:

    • PFormSelect, PFormTextarea, PFormCheckbox; Those components accept the same props as PFormItem but they don't render a slot. Only difference is that PFormSelect also accepts a selectComponent prop to choose between VSelect, VAutocomplete, VCombobox. Default is VSelect.
  • PSignaturePad: v-modelled wrapper for vue-signature-pad. It also has Clear Signature and Refuse to Sign controls in it.

  • PCallAttendees: Renders a VSelect with contacts of the current account as its items. The model can be controlled from outside with a v-model. However, it is not necessary to provide the v-modelas the default behavior is to send the selected values to the getParamsForSubmission as the attendees. Moreover, the getParamsForSubmission parser can also be overwritten with the parser prop.

  • PZeroInformation: Renders the zero card of the current account. Can also render the account address if the showAccountAddress props set to true. The required props are accountName and accountId.

  • PContentPresented: Renders the presented content during the call and sends the selected ratings to the getParamsForSubmission at the fileRatings field.

  • PContentPresentedWithChildren: Renders the presented content with the child pages. It is a accordion and the files are rated at the fields;

    • fileRatings: overall ratings of the rated children
    • subfileRatings: ratings of the child pages

# Composable

useWithForm This helper composable makes working with forms easier for developers. It has three parameters to work with each feature a form should have.

  1. parser: This parameter is a callback function, which is called in window.getParamsForSubmission, before sending the JSON string to the backend. This function's returned object gets merged to the object that will be send with getParamsForSubmission. This gives us opportunity to build data that'll be sent within the components.

  2. initializer: This parameter is an options object that acts as the initialize functionality for the given form field. This parameter handles the precall-postcall data binding, fills the fields with previous data when resuming and when none of them is available, fills the field with the default value. There are two alternative ways to use the initialization functionality - one is for the more complex situations where you define each steps function; save, resume, defaultValue, precallValue.

    • save gets called when the state needs to saved to be used when continued

    • resume gets called when the state needs to be filled when postcall gets loaded

    • precallValue gets called at the first initialization with the helper usePrecallData provided to the callback as the first parameter, if you call this helper with the value's expected field name on the object provided by setParameters (on iOS it checkes to params.currentCallObject.eventJSON.precallJSON object on windows it checks params.eventJSON) you can get the value that's filled on the precall and change this field model value to show that prefilled value.

    • defaultValue gets called if there is no resume or precall data provided for the field. Can be async function - and default data initialization for the form components should be done in this step.

      Second and more simple way to do is;

    • id: the field that will be used to store the ref's value to the localStorage when getDataObj is being called.

    • ref: is the ref that needs to be stored within the localStorage. It has to be a refobject.

    • defaultValue: same as above

    • precallField: key string of that fields eventJSON representation

  3. validator - optional: This parameter is another callback function which gets called in the window.canSubmit is called. So this callback gives us the ability to validate the current state of the component before sending the data to the backend. If the state is valid then this function should return true and false otherwise.

# Code example

Let's build a component that uses useWithForm.

<template>
  ...
</template>

<script>
  ...

  export default defineComponent({
    name: 'ExampleComponent',
    setup() {
      ...
      const examplesForPostcall = ref(...)

      // params recieved is the current state of the sfdc object that's going to be sent to backend
      // returned object with examples added replaces the sfdc object that's goint to be sent to backend
      function parseExamples() {
        return {
          examples: examplesForPostcall.value
        }
      }

      function validateExamples() {
        let valid = true

        ...

        if (isValid) {
          return true
        }

        showAlertBox('Warning', 'Examples is not valid')
        
        return false
      }
      
      //  There are two alternative ways to use the resuming functionality - one is the previous version of resume&save functions for the complex scenarios and for the simple scenarious where there is only one `ref` needed to be saved.

      const resumer = {
        precallValue: (usePrecallField) => {
          const precallValue = usePrecallField('MyExamplePrecallField')

          examplesForPostcall.value = precallValue
        },
        defaultValue: async () => {
          const someDbEntry = await query('SELECT foo FROM Bar WHERE Baz = "Buz"')

          examplesForPostcall.value = someDbEntry[0]
        },
        save() {
          return {
            fieldToSave: examplesForPostcall.value
          }
        },
        resume(savedObj) {
          examplesForPostcall.value = savedObj.fieldToSave
        }
      }
      
      // or the resumer can be a simple object that contains `id` and the `ref`.
      
      const resumer = { 
        id: 'aUniqueId',
        ref: fieldToSave,
        precallField: 'MyExamplePrecallField',
        defaultValue: async () => {
          const someDbEntry = await query('SELECT foo FROM Bar WHERE Baz = "Buz"')

          examplesForPostcall.value = someDbEntry[0]
        } 
      } 

      useWithForm(parseExamples, resumer, validateExamples)

      ...
    },
  })
</script>