0

Not sure, how should I explain this issue but probably my code snippet can explain this, I have a JS object which I've defined like below:

// This is my current Implementation of code
Class OptionCls {
  Constructor(){
    this.dataObj = {
      name: '',
      selectedValue: '',
      options: [],  
    }
  }

  setOptions(optionArray){
    this.dataObj.options = this.prepareOptions(optionArray);
  }

  prepareOptions(options){
    for(let obj of options){
        obj.label = obj.label ? obj.label : '';
        obj.value = obj.value ? obj.value : '';
        // automated properties for dropdown options
        Object.defineProperty(obj, '_id', {
            value: uniqueId()
        });
     }
     return options;
  }

  // class end
}

I call setOptions() method and pass my array of object to set the dataObj.options.

Now I would like to calculate or define a getter accessor property in the dataObj.options named as selected which should automatically read the parent property dataObj.selectedValue and based on that it should return the value, something like:

prepareOptions(options){
   for(let obj of options){
        obj.label = obj.label ? obj.label : '';
        obj.value = obj.value ? obj.value : '';
        // automated properties for dropdown options
        Object.defineProperty(obj, '_id', {
            value: uniqueId()
        });
        Object.defineProperty(obj, 'selected', {
            get(){
               return this.dataObj.selectedValue.split(',').includes(this.value); // Now over here `this` will be refer to local this scope not the parent object
            }
        });
    }
    return options;
}

At the end, output of dataObj should be look like this:

{
  name: '',
  selectedValue: 'us,uk',
  options: [
     {
       _id: "13",
       label: "United States",
       value: "us",
       selected: true
     },
     {
       _id: "11",
       label: "Australia",
       value: "au",
       selected: false
     },
     {
       _id: "10",
       label: "United Kingdom",
       value: "uk",
       selected: true
     }
  ]  
}

How can I achieve this, so far I tried but not able to reference this selectedValue in the nested object with this reference

user2809299
  • 149
  • 2
  • 13
  • What is not correctly working with your current getter? Can you show us the issue with a [code snippet](https://meta.stackoverflow.com/questions/358992/ive-been-told-to-create-a-runnable-example-with-stack-snippets-how-do-i-do)? – Nick Parsons Jun 21 '22 at 14:09
  • Sorry let me modify the code, actually the problem is accessing that in the object, because `this` refers to the local or current scope – user2809299 Jun 21 '22 at 14:10
  • Your code seems to work just fine, except there is nothing sets `selectedValue`, therefor `selected` will always be false. – vanowm Jun 21 '22 at 14:14
  • I updated the code, earlier I miss to provide the whole context with the reference of `this` – user2809299 Jun 21 '22 at 14:19
  • 1
    @user2809299 before the `Object.defineProperty()` with the getter (or even the for loop) with the getter, create a variable that holds your object `const dataObj = this.dataObj;`, then refer to it inside of the getter `dataObj.selectedValue.split(',')...` – Nick Parsons Jun 21 '22 at 14:21

1 Answers1

1

Just create a variable with the object outside of the getter scope, and also, Javascript is case sensitive, so class is not equal to Class and it's constructor() not Contstructor()

// This is my current Implementation of code
class OptionCls {
  constructor(){
    this.dataObj = {
      name: '',
      selectedValue: 'uk,us',
      options: [],  
    }
  }
  setOptions(optionArray){
    this.dataObj.options = this.prepareOptions(optionArray);
  }

  prepareOptions(options){
     for(let obj of options){
          obj.label = obj.label ? obj.label : '';
          obj.value = obj.value ? obj.value : '';
          // automated properties for dropdown options
          Object.defineProperty(obj, '_id', {
              enumerable: true, //show it in console
              value: uniqueId()
          });
          const dataObj = this.dataObj; //"this" is the class object in this scope
          Object.defineProperty(obj, 'selected', {
              enumerable: true, //show it in console
              get(){
                 return dataObj.selectedValue.split(',').includes(this.value); // Now over here `this` will be refer to local this scope not the parent object
              }
          });
}
      return options;
  }
  // class end
}

function uniqueId()
{
  return ++uniqueId._id;
}
uniqueId._id = 0;

const test = new OptionCls();
test.setOptions([
{
 label: "United States",
 value: "us",
},
{
 label: "Australia",
 value: "au",
},
{
 label: "United Kingdom",
 value: "uk",
},
{
  label: "ok",
  value: "nothing",
},
{
  label: "test",
  value: "blah",
},

]);

console.log(test.dataObj);
vanowm
  • 9,466
  • 2
  • 21
  • 37