1

I am making a custom field via a module.

I have an editableTableField that will hold the actual field values saved to an entry and I have other HTML elements that are used to grab data from a controller.

On button click, I need to take the data that is returned via my custom javascript and insert it into the table.

Is it possible to hook into the field and dynamically insert data into the field? Or do I have to create the html and manage the iterators and append it?

Here's an example of how I'm grabbing the data in JS

      // add zips in state
      $('#fields-add-state-zips').on('click', function() {
         var ajaxdata = {
            area: 'state',
            state: $stateSelect.val()
         };

         getDataFromArea(ajaxdata, function(locationData) {
            console.log(locationData);
         });
      });

Which calls my controller route:

    public function actionGetLocationsInArea() {
        $module = BulkAssignPostals::getInstance();

        $area = Craft::$app->request->post('area');

        $state = Craft::$app->request->post('state');
        $county = Craft::$app->request->post('county');
        $city = Craft::$app->request->post('city');
        $zip = Craft::$app->request->post('zip');

        $data = [];
        isset($state) ? $data['state'] = $state : $data['state'] = "";
        isset($county) ? $data['county'] = $county : $data['county'] = "";
        isset($city) ? $data['city'] = $city : $data['city'] = "";
        isset($zip) ? $data['zip'] = $zip : $data['zip'] = "";


        $res = Service::getLocationsInArea($area, $data);

        return json_encode($res);
    }

which calls my service

    public static function getLocationsInArea($area, $data) {
        $locations = [];

        switch ($area) {
            case "state":
                if (isset($data['state'])) {
                    $state = $data['state'];
                    $locations = Model::getLocationsInState($state);
                }
                break;
            case "county":
                if (isset($data['state']) && isset($data['county'])) {
                    $state = $data['state'];
                    $county = $data['county'];
                    $locations = Model::getLocationsInCounty($state, $county);
                }
                break;
            case "city":
                if (isset($data['state']) && isset($data['county']) && isset($data['city'])) {
                    $state = $data['state'];
                    $county = $data['county'];
                    $city = $data['city'];
                    $locations = Model::getLocationsInCity($state, $county, $city);
                }
                break;
            case "zip":
                if (isset($data['zip'])) {
                    $zip = $data['zip'];
                    $locations = Model::getLocationByZip($zip);
                }
                break;
            default:

        }

        return [
            'locations' => $locations
        ];
    }

which uses my model

    public static function getLocationsInState($state) {
        return PostalLocations::find()
        ->select('state_abbr,county,city,zip')
        ->where(['state_abbr' => $state])
        ->asArray()
        ->all();
    }

Edit:

I've come up with some javascript, but it feels very hacky and I'm hoping theres a better way. perhaps some craft JS hook of sorts. I'm not sure.

Here's my JS

     function addToTableField(rows) {

      $table = $('#fields-bulkAssignPostalsassignedPostals');
      $trCount = $table.find('tbody').find("tr").length - 0;

      rows.locations.forEach(function(row) {
         $table.find('tbody').append(
            $('<tr></tr>').attr('data-id', $trCount)
         );

         for (var key in row) {
            $table.find('tr[data-id='+$trCount+']').append(
               $('<td></td>').attr('class', 'textual').append(
                  $("<textarea></textarea>").attr('name', 'fields[bulkAssignPostals][assignedLocations]['+$trCount+']['+key+']').html(row[key])
               )

            );

         }
         $table.find('tr[data-id='+$trCount+']').append(
            '<td class="thin action"><a class="move icon" title="Reorder"></a></td>',
            '<td class="thin action"><a class="delete icon" title="Delete"></a></td>'
         );

         $trCount++;

      });


   }
1

I would use a custom controller that requests the javascript data and then appends it to your table with a method like:

public function appendDataToTable($entryId, $jsData) {
    $entry = \craft\elements\Entry::find()->id($entryId)->one();
    $tableValue   = $entry->getFieldValue( 'editableTableField' );
    $tableValue[] = [
        'col0' => $jsData,
    ];
    $entry->setFieldValue( 'editableTableField', $tableValue );
}

...if u need an example for the controller let me know, i am on the phone right now:

| improve this answer | |
  • thanks for the response. I'd like to see an example if you don't mind. Wouldn't I still need to create the HTML via js so it's populated on the front-end once they click the button? also, i've added some code examples of how my flow works – good_afternoon Jun 25 '19 at 14:44
  • I'm able to append data to the table now via a controller, but I'm confused about the JS. I'm not sure if I have to manually insert <tr> with the appropriate iteration from scratch. Then I wouldn't need to use a controller method since saving an entry will save whatever is in the table – good_afternoon Jun 25 '19 at 16:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.