HTML Custom Widget

Hello,

I have just bought the small instance and I’m really satisfied with the features available.

Now I have tried the custom widget available in the docs under the name of “devicePropertyWidget”, trying to edit it to get what I need but I’m not an HTML Programmer.

Here’s the html code after some editing:

<form class="form-validation m-t" ng-submit="save()">
    <fieldset ng-disabled="api.state==api.status.RUNNING || !api.allowed()">
    
        <div class="row wrapper-xs">
            <label class="col-sm-12"><strong>Time in Seconds</strong></label>
            <div class="col-sm-12">
                <input type="number" class="form-control" placeholder="NaN" ng-model="value.ecDSc" min="-1" "maxlength="3" required>
            </div>
        </div>
        
        <div class="wrapper-xs">
            <div class="alert alert-danger alert-dismissible m-b-sm" ng-if="api.state===api.status.ERROR">
                <a href="" class="close" data-dismiss="alert" aria-label="close">&times;</a>
                <strong><i class="far fa-thumbs-down"></i> Ooops!</strong> Cannot process your request. Error {{api.code}} ({{api.message}})
            </div>
           
            <button class="btn btn-success btn-addon" type="submit" ><i><span ng-class="{'fa fa-check': api.state!=api.status.RUNNING, 'fa fa-spinner fa-pulse' : api.state==api.status.RUNNING}"></span></i>Update</button>
            <div class="alert-success" ng-if="api.state==api.status.RUNNING">
                <strong><i class="far fa-thumbs-up"></i></strong> 
            </div>
        </div>
    </fieldset>
</form>

what I’m trying to do is to display an icon, for example a thumbs up, after the submit is performed successfully.

The code above displays ‘thumbs up’ while it’s submitting and it shows up for a very short time then disappears.

How can I show the ‘thumbs up’ after the submit is performed successfully and to be shown for 1 sec then disappears.

Regards,

Hi @Tester

You are almost there with your code regarding the thumbs-up div. It would look like this:

<div class="alert alert-success alert-dismissible m-b-sm" ng-if="api.state===api.status.OK">
    <a href="" class="close" data-dismiss="alert" aria-label="close">&times;</a>
    <strong><i class="far fa-thumbs-up"></i> Property updated!</strong>
</div>

The status of the API changes after the request to update the property to api.status.OK. While waiting for the user to click the update button, the state would be api.status.IDLE, so you would need to update the save function in the js file of the widget to this:

$scope.save = function(){

    // just call our api to patch values
    $scope.api.patch({value: $scope.value}).then(result => {
        setTimeout(() => {
            $scope.api.state=$scope.api.status.IDLE;
        }, 1000)

    }).catch(error => {
                    
    });
 };

Hello Sir,

Thank you so much for the help.

I have been searching a lot for api.status attributes other than the ERROR and RUNNING, but I couldn’t find them.

It works now as expected, thanks.

Hello again @jaimebs
I’m stuck in another matter.

Simply asked, how can I assign a constant number to a certain device property as a result of clicking the Update button?

It’s the same custom widget mentioned here in the post but without any user input, just the update button setting a device property value.

Hi @Tester

In the save function just before the call to the api assing your value. For example:

$scope.save = function(){

    $scope.value.d = "constant";

    // just call our api to patch values
    $scope.api.patch({value: $scope.value}).then(result => {

    }).catch(error => {
                    
    });
 };

This will add or modify a value of the current device and property configured in the html widget.

Ooooh!!

I though about this but didn’t trust it will work this way.

Thank you again I shall try this now. :smiling_face_with_three_hearts: :heart_eyes:

1 Like

Hello again @jaimebs ,

my next stop is: how could I toggle checkbox state on or off based on a property value?
So when a property value is 1 the checkbox is on and when the property value is 0 the checkbox is off.

<3

Hey @Tester

A checkbox is very similar to a switch, or to be more precise, a switch is a checkbox. Just modify the CSS classes of the switch in the example to “i-checks m-b-none m-t-xs”. A full example for a checkbox field would be:

<div class="row wrapper-xs">
    <label class="col-sm-12"><strong>Value C</strong></label>
    <div class="col-sm-12">
        <label class="i-checks m-b-none m-t-xs">
            <input type="checkbox" ng-model="value.c">
            <i></i>
        </label>
     </div>
</div>

Regarding saving the value as 1 or 0 you would need to treat the value in the js file when reading and saving into the property, as the checkbox or switch will only be able to read and save true or false.

Hello @jaimebs ,

Reading and saving into the property this time is required to be done outside the submit function(save()), I have tried this, but didn’t change the property value.

angular.module('circFourTimeSet', [])
.directive('circFourTimeSet', function () {
    
    return {
        restrict: 'EA',
        scope: {
            source : "=",
            value:   "=",
            ts:      "="
        },
        templateUrl: function(){
            let url = document.querySelector("script[src*='circFourTimeSet.js']");
            return url.src.replace('.js','.html');
        },
        controller: function($scope, DeviceProperty){
            console.log("controller initialized!", $scope);
            
            // if we require to listen for value changes...
            $scope.$watch('value.cr4L', function(newValue, oldValue) {
                console.log("value has changed!", newValue, oldValue);
            });
            
            // watch for source changes to update our api endpoint
            $scope.$watch('source', function(newVal) {
                $scope.api = new DeviceProperty({device: $scope.source.device_property.device, property: $scope.source.device_property.property});
            });
            
            $scope.value.cr4L = true;
            
            $scope.save = function(){
                // just call our api to patch values
                $scope.api.patch({value: $scope.value}).then(result => {
                   
                   setTimeout(() => {
                   $scope.api.state=$scope.api.status.IDLE;
                   }, 1000);
                }).catch(error => {

                });
            };
        }
    };
});

I should first check for current property value whether it’s ‘1’ or ‘0’ and then update the property value to ‘true’ or ‘false’, but to do that I have to first try to change the property value in the js file outside the submit function which i couldn’t.

Oh, so I understand that on checkbox click you want to submit its new value to the property. Is that right?

If that is the case you need to create a new watch function for that ng-model and submit the values:

$scope.$watch('value.c', function(newValue, oldValue) {

     if (typeof oldValue != 'undefined' && typeof oldValue != 'number') { // don't update on property on widget load
                
         $scope.value.c = $scope.value.c ? 1 : 0; // from boolean to number

         $scope.api.patch({value: $scope.value}).then(result => {
                        
             // from number to boolean so the checkbox represents the correct value
             $scope.value.c = Boolean(newValue);
                        
             setTimeout(() => {
                 $scope.api.state=$scope.api.status.IDLE;
             }, 1000)

        }).catch(error => {
                    
        });
    } else if ( typeof newValue != 'undefined') {
        // from boolean to number
        $scope.value.c = Boolean(newValue);
    }
});

This would read a 1 or 0, represent the correct value in the widget and on change save the widget with 1 or 0. However I’d look into managing the property from the beginning as true or false, as the code here would be much easier.

@jaimebs , It works now thank you, I added it in the watch section and it works as expected.

Here it is what I have done

 // if we require to listen for value changes...
            $scope.$watch('value.cr4L', function(newValue, oldValue) {
                console.log("value has changed!", newValue, oldValue);
                if($scope.value.cr4L == 1){
                    $scope.value.cr4L = true;
                }
                else if($scope.value.cr4L == 0){
                    $scope.value.cr4L = false;
                }
                else{
                    $scope.value.cr4L = false;
                }
            });

Thank you for your support

1 Like

Hello again @jaimebs ,

I’m stuck in sending texts via my wifi module to the server, output resource don’t send text values, it only sends numeric value, why is that?!

There’s another solution where I send numeric values to the server and then in the server side, decode these values to texts, but this needs js and html files which deals with device resource instead of the device property.

Hi @Tester

As this issue has nothing to do with this topic, could you create a new one? Also, post your code so we can help you further, as you should be able to send text as resources.