What's the best way to represent a Year field in an Enterprise Geodatabase & Web AppBuilder?

643
2
Jump to solution
11-07-2016 06:31 PM
JasonMatney
New Contributor III

I have a Fiscal Year Start field in a Feature Class which is shared as a Feature Service in a Web Map > Web Mapping Application (built with Web AppBuilder) workflow. The field must only contain 4-digit years, therefore, I cannot set the field to data type 'Date'. Instead, the field uses a Short Int data type with precision 5 (I set the precision to 4 but ArcGIS automatically changes it back to 5). Here are the field properties:

Feature Class Properties

Layer Properties

Number Properties

Now, I can go into the config attribute settings in my Web Map and turn off the 1000 separator option. This works for displaying the years correctly in the Web Map. However, this does not carry over to the Web Mapping Application. When I use the Filter widget in the Web Mapping Application, the 1000 separator returns.

No 1000 Separator
Filter Widget Fail

I initially tried to get around this problem by using a Text field for year input, but that option does not work for this workflow due to the presence of a GeoForm - the GeoForm is  where data is entered for the project. The reason a text field does not work is because the GeoForm Fiscal Year Start field must throw an error if a non-4-digit-integer is entered, i.e., FY17, or 17.

Screenshot

Essentially then, my question is this - is there a better solution for representing a year in a geodatabase? This ideal solution would do the following:

  1. Have data entry limited to no more or less than 4-digits
  2. Throw an error if a non-integer was used during the data entry process in a GeoForm
  3. Would not use a 1000 separator to display a 4-digit integer in Web AppBuilder

Thanks in advance.

(By the way, is there a way to change the Error Message of 'Please enter a valid integer between -32768 and 32767.'? I'd much rather it said what the help text says, e.g., 'Enter a fiscal year as the four-digit year...'.)

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Esteemed Contributor

Jason,

   The fact that the filter widget does not respect the format in the web map is a bug in my opinion but will likely be viewed by esri as an enhancement request. I would call this into esri tech support. But in the mean time you can make this modification to WAB Dev edition to force the no 1000 separator in the filter and query widgets:

In the jimu.js\dijit\_SingleFilterParameter.js make this change to the _buildNumber function (Lines 81-85):

      _buildNumber: function(fieldInfo, part){
        /*jshint unused: false*/
        var def = new Deferred();
        html.setStyle(this.stringTextBoxContainer, 'display', 'none');
        html.setStyle(this.numberTextBoxContainer, 'display', 'block');
        html.setStyle(this.dateTextBoxContainer, 'display', 'none');

        this._hideDijit(this.numberTextBox);
        this._hideDijit(this.numberCodedValuesFS);
        html.setStyle(this.numberRangeTable, 'display', 'none');
        this._hideDijit(this.numberUniqueValuesSelect);

        var fieldObj = part.fieldObj;//name,shortType
        var valueObj = part.valueObj;//value,value1,value2
        var radioType = valueObj.type;//'value' or 'unique',not 'field'
        var operator = part.operator;
        var isNumBetween = operator === this.OPERATORS.numberOperatorIsBetween;
        var isNumNotBetween = operator === this.OPERATORS.numberOperatorIsNotBetween;

        var isRange = isNumBetween || isNumNotBetween;
        if(isRange){
          this._type = 3;
          html.setStyle(this.numberRangeTable, 'display', 'table');
          if(jimuUtils.isValidNumber(valueObj.value1)){
            this.numberTextBox1.set('value', valueObj.value1);
          }
          if(jimuUtils.isValidNumber(valueObj.value2)){
            this.numberTextBox2.set('value', valueObj.value2);
          }
          def.resolve();
        }
        else{
          html.setStyle(this.numberRangeTable, 'display', 'none');
          var codedValues = this._getCodedValues(fieldInfo);
          if(codedValues){
            this._type = 2;
            this._showDijit(this.numberCodedValuesFS);
            var numberCodedData = array.map(codedValues, lang.hitch(this, function(item, index){
              //item:{name,code},name is the code description and code is code value.
              var dataItem = lang.clone(item);
              dataItem.id = index;
              return dataItem;
            }));
            var numberCodedStore = new Memory({data:numberCodedData});
            this.numberCodedValuesFS.set('store', numberCodedStore);
            if(valueObj && jimuUtils.isValidNumber(valueObj.value)){
              var number = parseFloat(valueObj.value);
              var numberSelectedItems = array.filter(numberCodedData,
                lang.hitch(this, function(item){
                return parseFloat(item.code) === number;
              }));
              if(numberSelectedItems.length > 0){
                this.numberCodedValuesFS.set('value', numberSelectedItems[0].id);
              }
              else{
                this.numberCodedValuesFS.set('value', numberCodedData[0].id);
              }
            }
            else{
              this.numberCodedValuesFS.set('value', numberCodedData[0].id);
            }
            def.resolve();
          }
          else{
            if(radioType === 'unique'){
              this._type = 4;
              this._showDijit(this.numberUniqueValuesSelect);
              jimuUtils.getUniqueValues(this.url, fieldObj.name).then(
                lang.hitch(this, function(values){
                var selectedId = -1;
                //don't select the first value by default, issue #2477
                /*if(values.length > 0){
                  selectedId = 0;
                }*/


                var data = array.map(values, lang.hitch(this, function(value, index){
                  var label = value;

                  if(fieldObj.shortType === 'number'){
                    value = parseFloat(value);
                    if(fieldObj.name === "FY_Start" || fieldObj.name === "FY_End"){
                      label = value;
                    }else{
                      label = this._tryLocaleNumber(value);
                    }
                  }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

View solution in original post

2 Replies
RobertScheitlin__GISP
MVP Esteemed Contributor

Jason,

   The fact that the filter widget does not respect the format in the web map is a bug in my opinion but will likely be viewed by esri as an enhancement request. I would call this into esri tech support. But in the mean time you can make this modification to WAB Dev edition to force the no 1000 separator in the filter and query widgets:

In the jimu.js\dijit\_SingleFilterParameter.js make this change to the _buildNumber function (Lines 81-85):

      _buildNumber: function(fieldInfo, part){
        /*jshint unused: false*/
        var def = new Deferred();
        html.setStyle(this.stringTextBoxContainer, 'display', 'none');
        html.setStyle(this.numberTextBoxContainer, 'display', 'block');
        html.setStyle(this.dateTextBoxContainer, 'display', 'none');

        this._hideDijit(this.numberTextBox);
        this._hideDijit(this.numberCodedValuesFS);
        html.setStyle(this.numberRangeTable, 'display', 'none');
        this._hideDijit(this.numberUniqueValuesSelect);

        var fieldObj = part.fieldObj;//name,shortType
        var valueObj = part.valueObj;//value,value1,value2
        var radioType = valueObj.type;//'value' or 'unique',not 'field'
        var operator = part.operator;
        var isNumBetween = operator === this.OPERATORS.numberOperatorIsBetween;
        var isNumNotBetween = operator === this.OPERATORS.numberOperatorIsNotBetween;

        var isRange = isNumBetween || isNumNotBetween;
        if(isRange){
          this._type = 3;
          html.setStyle(this.numberRangeTable, 'display', 'table');
          if(jimuUtils.isValidNumber(valueObj.value1)){
            this.numberTextBox1.set('value', valueObj.value1);
          }
          if(jimuUtils.isValidNumber(valueObj.value2)){
            this.numberTextBox2.set('value', valueObj.value2);
          }
          def.resolve();
        }
        else{
          html.setStyle(this.numberRangeTable, 'display', 'none');
          var codedValues = this._getCodedValues(fieldInfo);
          if(codedValues){
            this._type = 2;
            this._showDijit(this.numberCodedValuesFS);
            var numberCodedData = array.map(codedValues, lang.hitch(this, function(item, index){
              //item:{name,code},name is the code description and code is code value.
              var dataItem = lang.clone(item);
              dataItem.id = index;
              return dataItem;
            }));
            var numberCodedStore = new Memory({data:numberCodedData});
            this.numberCodedValuesFS.set('store', numberCodedStore);
            if(valueObj && jimuUtils.isValidNumber(valueObj.value)){
              var number = parseFloat(valueObj.value);
              var numberSelectedItems = array.filter(numberCodedData,
                lang.hitch(this, function(item){
                return parseFloat(item.code) === number;
              }));
              if(numberSelectedItems.length > 0){
                this.numberCodedValuesFS.set('value', numberSelectedItems[0].id);
              }
              else{
                this.numberCodedValuesFS.set('value', numberCodedData[0].id);
              }
            }
            else{
              this.numberCodedValuesFS.set('value', numberCodedData[0].id);
            }
            def.resolve();
          }
          else{
            if(radioType === 'unique'){
              this._type = 4;
              this._showDijit(this.numberUniqueValuesSelect);
              jimuUtils.getUniqueValues(this.url, fieldObj.name).then(
                lang.hitch(this, function(values){
                var selectedId = -1;
                //don't select the first value by default, issue #2477
                /*if(values.length > 0){
                  selectedId = 0;
                }*/


                var data = array.map(values, lang.hitch(this, function(value, index){
                  var label = value;

                  if(fieldObj.shortType === 'number'){
                    value = parseFloat(value);
                    if(fieldObj.name === "FY_Start" || fieldObj.name === "FY_End"){
                      label = value;
                    }else{
                      label = this._tryLocaleNumber(value);
                    }
                  }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

View solution in original post

RobertScheitlin__GISP
MVP Esteemed Contributor

Don't forget to mark this question as answered by clicking on the "Correct Answer" link on the reply that answered your question.

0 Kudos