Key-Value Pair List custom field

Anyone already build a custom field that can do a list of arbitrary key-value pairs?

I imagine it would be persisted as a json associative array string in the backend; render with a list of textbox pairs with the ability to add/remove individual items. Reorder would be nice but not impossible.

I'm not a KO guy but this doesn't seem particularly difficult to me; thought I'd ask around before building.

0

Comments

1 comment
  • Official comment

    Hi Richard,

    I can't say I've seen one built, but you are correct in that it shouldn't be too difficult. There's actually an implementation for similar to what you are asking that we've built internally for some fields. Its an internal method so you can't access it, but it looks something like this:

    var viewModel = function (params) {                
    /*
    params.json - must be an observable
    */


    var self = this;

    function KeyValuePair(key, value) {
    this.Key = ko.observable(key);
    this.Value = ko.observable(value);
    }

    self.data = {
    json: params.json,
    keyValuePairs: ko.pureComputed(function () {
    var json = ko.unwrap(self.data.json),
    keyValuePairAry = [];

    if (typeof json !== 'undefined' && json !== null && json !== "") {
    var jsonParsed = JSON.parse(json);

    for (x in jsonParsed) {
    keyValuePairAry.push(new KeyValuePair(x, jsonParsed[x]));
    }
    }

    return keyValuePairAry;
    }),
    newKeyValuePair: ko.observable(new KeyValuePair())
    };

    self.methods = {
    addKeyValuePair: function () {
    var json = ko.unwrap(self.data.json),
    jsonParsed = {};

    if (typeof json !== 'undefined' && json !== null && json !== "") {
    jsonParsed = JSON.parse(json);
    }

    var newKeyValuePair = ko.toJS(self.data.newKeyValuePair),
    key = ko.unwrap(newKeyValuePair.Key);

    if (typeof key === "undefined" ||
    key === null ||
    key === "") {
    //do not add if the key is empty
    return;
    }

    //add new property to parsed json
    jsonParsed[key] = ko.unwrap(newKeyValuePair.Value) || "";

    //store json
    self.data.json(JSON.stringify(jsonParsed));

    //refresh new key value pair
    self.data.newKeyValuePair(new KeyValuePair());
    },
    deleteKeyValuePair: function (keyValuePair) {
    var json = ko.unwrap(self.data.json);

    if (typeof json !== 'undefined' && json !== null && json !== "") {
    jsonParsed = JSON.parse(json);

    delete jsonParsed[keyValuePair.Key.peek()];

    self.data.json(JSON.stringify(jsonParsed));
    }

    },
    };

    };

    And then the HTML is:

    <script type="text/html" id="json-editor">
       <!-- ko foreach: data.keyValuePairs -->
       <div class="row default hover-action">
       
           <div class="col-md-6">
               <div class="field-row">
                   <label class="control-label">
                       <span>Label</span>
                       <input type="text" class="form-control" data-bind="value: Key">
                   </label>
               </div>
           </div>
           <div class="col-md-6">
               <div class="field-row">
                   <label class="control-label">
                       <span>Value</span>
                       <input type="text" class="form-control" data-bind="value: Value">
                   </label>
               </div>
           </div>
           <div class="hover-action-btn">
               <button type="button" class="btn btn-danger btn-small btn-ecom-form-inline" data-bind="click: $parent.methods.deleteKeyValuePair">
                   <span class="icon" data-bind="css: ContentManager.Global.ActionButtons.Delete.Icon"></span>
               </button>
           </div>
       </div>
       <!-- /ko -->
       
       @* NEW ROW *@
       <div class="row default hover-action" data-bind="with: data.newKeyValuePair">
       
           <div class="col-md-6">
               <div class="field-row">
                   <label class="control-label">
                       <span>Label</span>
                       <input type="text" class="form-control" data-bind="value: Key">
                   </label>
               </div>
           </div>
           <div class="col-md-6">
               <div class="field-row">
                   <label class="control-label">
                       <span>Value</span>
                       <input type="text" class="form-control" data-bind="value: Value">
                   </label>
               </div>
           </div>
           <div class="hover-action-btn">
               <button type="button" class="btn btn-primary btn-small btn-ecom-form-inline" data-bind="click: $parent.methods.addKeyValuePair">
                   <span class="icon" data-bind="css: ContentManager.Global.ActionButtons.New.Icon"></span>
               </button>
           </div>
       </div>
    </script>

     

     

    Comment actions Permalink

Please sign in to leave a comment.

Didn't find what you were looking for?

New post