Best practises for property validation and min/max values

User settings are defined in properties.xml as <resources><properties>....</properties></resources> those settings can be changed by user in Garmin Express or Garmin connect mobile, and in Eclipse Connect iq / App settings editor.

Is there a way to set minimum and maximum values for numbers?
Is there a way to set list of available values instead of "open" values?

What is the best practise for using the app.validateProperty() function? I feel like I'm doing 2x work and 3x mistakes when
  • Hi, you can set min / max for numeric valus in the settings

    <setting propertyKey="@Properties.z3" title="@Strings.zone3">
    <settingConfig type="numeric" min="61" max="75" required="true"/>
    </setting>


    you can also define a list of available values

    <setting propertyKey="@Properties.pace_info" title='@Strings.show_pace_info'>
    <settingConfig type="list" required="true">
    <listEntry value="0">@Strings.none</listEntry>
    <listEntry value="1">@Strings.avg_pace</listEntry>
    <listEntry value="2">@Strings.curr_pace</listEntry>
    <listEntry value="3">@Strings.cad</listEntry>
    </settingConfig></setting>


    hope that information helps you.
  • Thanks. I already found that information from http://developer.garmin.com/connect-iq/programmers-guide/resource-compiler/ page later.

    My next question is how do I validate a date from Settings? I could ask day/month, but I don't know how to validate days per month (how to not get 31st of february) from GE/GCM.
  • If you set the type field to date, you shouldn't need to do validation. The user is presented a date picker on the PC (or mobile device) and the date should be validated there. I believe the following would work, but I haven't tested it.

    <resources>
    <properties>
    <property id="DateTest" type="number">1451606400</property>
    </properties>

    <settings>
    <setting propertyKey="@Properties.DateTest" title="@Strings.DateTestTitle">
    <settingConfig type="date" required="true" min="1388534400" max="1704067200" />
    </setting>
    </settings>
    </resources>


    Of course that will be a complete date time (year, month, day, hour, minute, second). If you just want the user to supply part of that (say just the month and day), you'd have to figure something out.

    If you really need to validate a date in MonkeyC, the following code should work. I haven't tested it, but it should be close.

    //! returns true if `value' is inside the range [ `min', `max' ]
    function is_in_range_inclusive(value, min, max) {
    return !(value < min || max < value);
    }

    //! returns true if `year' is a leap year, otherwise false
    function is_leap_year(year)
    {
    if (year % 4 != 0) {
    return false;
    }
    else if (year % 100 != 0) {
    return true;
    }
    else if (year % 400 == 0) {
    return true;
    }

    return false;
    }

    const month_days = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];

    //! returns the number of days in the given `month' of the given `year'. returns
    //! null if `month' is outside of the range [1, 12].
    function days_in_month_year(year, month) {

    if (!in_range_inclusive(month, 1, 12)) {
    return null;
    }

    var days_in_month = month_days[month];

    if (month == 2 && is_leap_year(year))
    days_in_month += 1;
    }

    return days_in_month;
    }

    //! returns true if `year', `month', and `day' represent a valid proleptic Gregorian date,
    //! otherwise returns false.
    function is_valid_date(year, month, day) {

    var days_in_month = days_in_month_year(year, month);
    if (days_in_month == null) {
    return false;
    }

    if (in_range_inclusive(day, 1, days_in_month)) {
    return true;
    }

    return false;
    }

    //! returns true if `hour', `minute', and `second' represent a valid time, otherwise
    //! returns false.
    function is_valid_time(hour, minute, second) {
    return in_range_inclusive(hour, 0, 23) &&
    in_range_inclusive(minute, 0, 59) &&
    in_range_inclusive(second, 0, 59);
    }

    //! returns true if `year', `month', `day', `hour', `minute' and `second' represent
    //! a valid date-time, otherwise false. Note that this is not valid for some local time
    //! values. e.g., the witching hour that occurs when clocks leap forward due to a
    //! daylight saving time transition. for this function to work perfectly, you must get
    //! the date-time value in UTC time, validate it, and then convert that to local time.
    function is_valid_date_time(year, month, day, hour, minute, second) {
    return is_valid_date(year, month, day) && is_valid_time(hour, minute, second);
    }
  • If you set the type field to date, you shouldn't need to do validation. The user is presented a date picker on the PC (or mobile device) and the date should be validated there. I believe the following would work, but I haven't tested it.


    Yes. That actually did work. I was a bit confused of the "date" value based on the web pages information, but the date picker was what I was looking for. I submitted my T-minus app already. :)
  • Yes. That actually did work. I was a bit confused of the "date" value based on the web pages information, but the date picker was what I was looking for. I submitted my T-minus app already. :)


    Just be careful, there are a lot of known bugs related to the date picker in terms of how the epoch is handled on all different platforms in the ecosystem.
    Each of these platforms have issues:

    Garmin Express (both Win and Mac)
    Garmin Connect Mobile (both Android and iOS)
    CIQ SDK

    All have been reported to Garmin in the past and we are still waiting for fixes.

    If you encounter weird behaviour, just let me know and I will assist you.
  • Just be careful, there are a lot of known bugs related to the date picker in terms of how the epoch is handled on all different platforms in the ecosystem.
    If you encounter weird behaviour, just let me know and I will assist you.


    .. and I immeditially gave up on trying to make T-app work on event's time zone and dst. Not with these APIs. :-)
  • It sounds like you're probably best off to just prompt for the day and month and time properties separately and then build a Moment for them.

    Travis