Select month and year DateTimePicker

Hello, I need to pass to a script just the month and year in an input component.

I am not able to customize the component below to show only the months and years for selection.

Has anyone already created a similar component?

image

image

Why don't you place two Dropdowns - one for the month and one for the year?

2 Likes

Dropdown with dates seems like your best option.
If you want to retrieve just the month from the date component you could add a custom property with the following expression:

dateFormat({value},"yyyy-MM")

Here`'s a result:

You can check out more about the dateFormat() expression here:
https://docs.inductiveautomation.com/display/DOC81/dateFormat

Also, there's the Overflow style property, it might be useful in some other instance since in this one it would reduce the component to basically two dropdowns anyway.

The problem with this is that the value does not change unless you select the actual day on the calendar.

How would one go about the years drop down? If the time spans decades, and I'm assuming that each year value would be hard-coded, this would take a lot of work, and probably won't be dynamic.

Is there a script that could pull a range of years, based on the current year, and populate the values and options?

  • On your dropdown create a custom property.
    ddYears : 10
  • Right click on the dropdown component, select Convfigure Events.
  • Add in the code as shown below.
Dropdown onStartup code
def runAction(self):
	options = []
	ddYears = self.custom.ddYears
	thisYear = system.date.getYear(system.date.now())
	
	for i in range(ddYears):
		yyyy = thisYear + i
		options.append({"value": yyyy, "label": yyyy})
	
	self.props.options = options

Make sure that all the indentations are correct and either all spaces or all tabs.

1 Like

This really depends on your use-case. Do you only need years after this year? Including this year? How far out?

The script provided by @Transistor should get you most of the way, but this is probably better realized as a binding with a transform. Bind against an expression which gets you the current year, then add options as you see fit within a transform:

options = []
options.append({"value": value, "label": value})  # include current year
for i in range(self.custom.year_range):  # where year_range is how far into the past/future you want to include years
    year = value - i
    options.append({"value": year, "label": year})  # include previous years
    year = value + i
    options.append({"value": year, "label": year})  # include coming years

I got this to work, but you do have to change the value of thisYear as it loops through, otherwise you get the same number.

def runAction(self):
	options = []
	ddYears = self.parent.custom.year_range
	thisYear = system.date.getYear(system.date.now())
	
	options.append({'value': thisYear, 'label': thisYear})
	
	for i in range(ddYears):
		thisYear = thisYear - 1
		options.append({'value': thisYear, 'label': thisYear})
		
	self.props.options = options

I am not sure which binding to use to get the current year.

It does not like this one:
image

Nor this:

options = []
options.append({"value": {value}, "label": {value}})
for i in range({parent.custom.year_range}):
	year = year - 1
	options.append({"value": year, "label": year})

I think you have mixed parts from expression and script transforms. You will want to change to a script transform. You'll reference the value as a variable with the name of value.

options = []
options.append({"value": value, "label": value})
for i in range(parent.custom.year_range):
	year = year - 1
	options.append({"value": year, "label": year})
return options

However I think there is a flaw in your code as year is never set.

It is also probably worth mentioning that calling now() without a polling rate will default to updating every second. So it will be worth setting to 0.

I see:

def transform(self, value, quality, timestamp):
	year = int(value)
	options = []
	options.append({"value": year, "label": year})
	for i in range(0, self.parent.custom.year_range):
		year = year - 1
		options.append({"value": year, "label": year})
	return options

But I don't see polling options for getting the date, unless there is some expression that could limit that.

No, my code is automatically incrementing because i increments on each loop.

	for i in range(ddYears):
		yyyy = thisYear + i

You could turn off polling in the expression binding by specifying the polling rate on now.
getYear(now(0))

1 Like