# Delete variable data from Device Groups or Types

Use this example to build an HTML Canvas widget that deletes variable data from **Device Types** and **Device Groups.**

Ubidots supports two device grouping types: **Device Types** and **Device Groups**.

* Create the structure. Paste the following into the HTML code editor tab:

```html
<p id="deviceLabelMessage"></p>

<div id="inputContainer"></div>

<form id="date-form">
	<label for="date1">Start date:</label>
	<input type="datetime-local" id="date1" name="date1" value="2023-01-01T00:00" required>
	<br>
	<label for="date2">End date:</label>
	<input type="datetime-local" id="date2" name="date2" value="2023-01-01T12:00" required>
	<br>
	<button type="submit">Delete values</button>
</form>
```

This creates the date selectors, the variable input, and the submit button.

* Set the logic. Paste the following into the JavaScript tab:

```javascript
var ubidots = new Ubidots;
var dashboardID;
var ubidotsToken;
var selectedVariableID;
var selectedVariableLabel;
var dashboardObject;
var inputContainer;
var displayedMsg;
var firstTime = true;


ubidots.on('ready', async function()
{
	//obtain the required variables
    dashboardID = ubidots.dashboardObject.id;
    ubidotsToken = ubidots.token;
	
	//get the dashboard object from ubidots api
    dashboardObject = await getDashboardObject(dashboardID, ubidotsToken);
	//get the element containing either the dropdown menu or the input text
    inputContainer = document.getElementById("inputContainer");  
	//get the elemente displaying the message
    displayedMsg = document.getElementById("deviceLabelMessage");
	//change the widget so it displays either a dropdown menu or an input type
    await setGUIAccordingToDeviceTypeFilter(dashboardObject, inputContainer, displayedMsg);
	firstTime = false;
	console.log("EXIT");
});

ubidots.on('selectedDevice', async function (data) 
{
	if(!firstTime)
	{
		//selectedVariableLabel = getVariableLabelFromContainer(inputContainer);
		deleteDropdownItems(inputContainer);
		await setGUIAccordingToDeviceTypeFilter(dashboardObject, inputContainer, displayedMsg);

		//populateDropdownItems(deviceVariables, dropdown);
		//displayDeviceData(deviceID, deviceLabel, token);
	}
});



document.getElementById('date-form').addEventListener('submit', async function(event)
{
	event.preventDefault();
	
	const ts1 = toTimestamp(document.getElementById('date1').value);
	const ts2 = toTimestamp(document.getElementById('date2').value);
	
	if(!assertTimestamps(ts1, ts2))
	{
		return false;
	}

	selectedVariableLabel = getVariableLabelFromContainer(inputContainer);
	console.log(selectedVariableLabel);
	
	const devicesInDashboardIDs = await getDashboardDevicesIDs(dashboardID, ubidotsToken);
	const req = await isTypesOrGroups(dashboardObject, deleteVariableFromGroup, deleteVariableFromGroup, devicesInDashboardIDs, ubidotsToken, selectedVariableLabel, ts1, ts2);
	console.log(req);
});

function populateDropdownItems(items, dropdownObj)
{
	var isFirst = true;
	items.forEach(function(item)
	{
		var option = document.createElement('option');
  		option.text = item.label + " : " + item.id;
  		dropdownObj.add(option);
		isFirst = false;
	});
}


function deleteDropdownItems(dropdown)
{
	while (dropdown.firstChild) 
	{
    	dropdown.removeChild(dropdown.firstChild);
  	}
}

function assertTimestamps(ts1, ts2)
{
	if(ts1 > ts2)
	{
		console.error("ERROR: end date being earlier than start date.", ts1, ts2);
		console.log("startDate: ", ts1);
		console.log("endDate: ", ts2);
		return false;
	}
	return true;
}

async function deleteVariableFromGroup(deviceID = [], ubidotsToken, variableLabel, ts1, ts2)
{
	const promisesList = [];
	await Promise.all(deviceID.map(async (id) => 
	{
  		const deviceVariables = await getDeviceVariables(id, ubidotsToken);
 		deviceVariables.forEach(async (variable) => 
		{
    		if(variable.label === variableLabel) 
			{
				const req = await deleteVariable(variable.id, ts1, ts2, ubidotsToken);
				promisesList.push(req);
    		}
  		});
	}));
	return promisesList;
}

async function isTypes(deviceID = [], ubidotsToken)
{
	console.log("ENTRY");
	return {"msg":1};
}

async function deleteVariable(variableID, ts1, ts2, ubidotsToken)
{
	var debugMsg = {"var id" : 0, "url": ".", "task id" : 0};
	const url = "https://industrial.api.ubidots.com/api/v2.0/variables/" + 
		variableID + "/_/values/delete/?startDate=" + ts1 + "&endDate=" + ts2;
	const response = await fetchWrapper(url, 'POST', ubidotsToken);
	debugMsg["var id"] = variableID;
	debugMsg["url"] = url;
	debugMsg["task id"] = response;
	return debugMsg;
}

function getVariableLabelFromContainer(container)
{
	var value = container.firstElementChild.value;	
	return value;
}

async function setGUIAccordingToDeviceTypeFilter(dashboardObject, inputContainer, displayedMsg)
{
    if(dashboardObject.context.deviceFilterType == 'device_type')
    {
        var a = await getDeviceVariables(ubidots.selectedDevice, ubidots.token);
        var labels = [];
        a.forEach(element =>
        {
            labels.push(element.label);
        });
    }
    isTypesOrGroups(dashboardObject, populateDropdown, populateTextField, inputContainer, displayedMsg, labels);
}

function populateDropdown(inputContainer, displayedMsg, dropdownElements)
{
    var dummyStr = '';
    dropdownElements.forEach(element =>
    {
        dummyStr = dummyStr + '<option value=\"' + element + '\">' + element + '</option>' + ' ';
    });
    inputContainer.innerHTML = `<select id="inputType">` + dummyStr + `</select>`;
    displayedMsg.innerText = "Select variable";
}

function populateTextField(inputContainer, displayedMsg)
{
	displayedMsg.innerText = "Enter a variable's label";
    inputContainer.innerHTML = `<input type="text" id="inputType">`;
}


function isTypesOrGroups(dashboardObject, typeCallback, groupCallback, ...rest)
{
    if(dashboardObject.context.deviceFilterType == "device_group")
    {
        return groupCallback(...rest);
    }
    else if(dashboardObject.context.deviceFilterType == "device_type")
    {
        return typeCallback(...rest);
    }
    else
        return {"ERROR" : "device filter type not recognized"};
}

async function getDeviceVariables(deviceID, token)
{
	const url = 'https://industrial.ubidots.com/api/v2.0/devices/' + deviceID + '/variables';
	const response = await fetchWrapper(url, 'GET', token);
	return response.results;
}

async function getDashboardObject(dashboardID, ubidotsToken)
{
    const url = 'https://industrial.api.ubidots.com/api/v2.0/dashboards/' + dashboardID;
    const req = await fetchWrapper(url, 'GET', ubidotsToken);
    return req;
}

async function getDashboardDevices(dashboardID, ubidotsToken)
{
    const url = 'https://industrial.ubidots.com/api/-/dashboards/' + dashboardID + '/devices?sort_by=name&page_size=500';
    const method = 'GET';
    const req = await fetchWrapper(url, method, ubidotsToken);
    return req;
}

async function getDashboardDevicesIDs(dashboardID, ubidotsToken)
{
    var req = await getDashboardDevices(dashboardID, ubidotsToken);
    var l = [];

    req.results.forEach(function(item)
	{
        l.push(item.id);
    });
	return l;
  
}

async function getDeviceObject(deviceID, ubidotsToken, filters = null)
{
	var url = 'https://industrial.api.ubidots.com/api/v2.0/devices/' + deviceID + '/';
	url = filters == null ? url : url + filters;
	const request = await fetchWrapper(url, 'GET', ubidotsToken);
	return request;
}

async function fetchWrapper(url, method, token = null, payload = null)
{
	const options =
	{
    	method: method,
		headers: {'Content-Type' : 'application/json'}
	};

	if (payload)
	{
    	options.body = JSON.stringify(payload);
  	}

  	if (token)
	{
    	options.headers['X-Auth-Token'] = token;
  	}

	const response = await fetch(url, options);
	const jsonData = await response.json();
	return jsonData;
}


function toTimestamp(date) 
{
	const dateObj = new Date(date);
	const timestamp = dateObj.getTime();
	return timestamp;
}
```

This implementation displays a different UI depending on whether the current dashboard uses a device type or device group filter. For device type dashboards, the variables shared by the selected device type appear in a dropdown menu. For device group dashboards, a text box appears so the user can enter the label of the variable to delete.\
\
The following GIF shows the widget in both dashboard types:

<figure><img src="/files/pqS1Ss3K2P5CvSldETWv" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dev.ubidots.com/dashboards-and-widgets/html-canvas/examples/delete-variable-data-from-groups-or-types-of-devices.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
