How to map from one dynamic object to another in typescript ๐ŸŒ

I wanted users to be able to select a style from a drop down at GeoJson-Styler (jcianci12.github.io)

The user can choose how they want their geoJSON objects styled. at the moment the options are colour, text, and opacity.

The classes look as follows:

export class opacity {
  constructor() {
    this.opacityvalue = 1;
    this.rulename = 'opacity';
  }
  opacityvalue: number;
  rulename: rulename;
}
export class colour {
  constructor() {
    this.colour = 'grey';
    this.rulename = 'colour';
  }
  colour: string;
  rulename: string;
}

export class text {
  constructor() {
    this.textvalue = '';
    this.rulename = 'text';
    this.latoffset = 0
    this.lngoffset = 0
  }
  textvalue: string;
  rulename: string;
  latoffset:number;
  lngoffset:number;
}

As you can see the text class is different to the other classes and has some extra properties. I want the extra properties to be visible to the end user when they choose the text option, like so:

As you may already know, Javascript doesnt know about classes. The closest thing is to make sure your object is populated with all the fields that exist in the class.

So as the code above shows, the constructors help achieve this.

I found that when the user changed the latoffset and the lngoffset, the values were not ‘sticking’. This was because a new object was being created each time. I needed a way to create the new object, and populate the objects values from the users previous settings (if any).

Here is what I managed to come up with:

 updateRule(index: number, stylerule: stylerule) {
    //get the matching class by the rule name
    let matchingrule = [new opacity(), new colour(), new text()].find(
      (i) => i.rulename == stylerule.ruletype.rulename
    );
    //loop through the keys of the new object and if there 
    //is a matching key from the users settings, assign it 
    Object.keys(matchingrule!).forEach((key: string) => {
      if ((stylerule.ruletype as any)[key]) {
        (matchingrule as any)[key] = (stylerule.ruletype as any)[key];
      }
      //console.log("matching rule",matchingrule,"key",key,"index",ind,"stylerule",stylerule)
    });

    //This is needed because angular wont update an object when its child properties change.
    //therefore we can clear the object and then reassign it
    let _temp = this.stylerules;
    this.stylerules = [];
    this.stylerules = _temp;
    this.stylerules[index] = {
      column: stylerule.column,
      ruletype: matchingrule!,
    };
    //this is if you want to emit the change up the tree
    this.stylerulesChange.emit(this.stylerules);
  }

Now, when the user selects a style, the optional fields are rendered in the view ๐Ÿ‘


Posted

in

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *