Programmatically make HTML control dirty?

peter0611
Tera Contributor

Hello! I built a form in a widget with a couple of controls. Here is one example in the HTML template:

 

<input ng-pattern="namePattern" ng-model="c.first_name" id="first_name" name="first_name" autocomplete="given-name" type="first_name" class="form-control" ng-minlength="1" ng-focus="c.sendFieldStatusMessage(userForm, $event)" aria-required="true" required />

 

Now I will be pre-populating some of these controls on load via the client script, meaning that they will still be in a pristine\untouched state. How can I mark on or more of these controls as dirty in the client controller? I tried using 

$<input_name>.markAsDirty(); but that gives an undefined error. I feel like I'm close to the answer but don't know the proper syntax or method to use. Any help is appreciated!
1 ACCEPTED SOLUTION

Iraj Shaikh
Mega Sage
Mega Sage

Hi @peter0611 

 

In AngularJS, which is typically used in ServiceNow widgets, you can interact with forms and their controls through the `$scope` object and the form directive. To mark a control as dirty, you would typically access the form and the control within your client controller and use the `$setDirty()` method on the control.

 

Here's how you can do it in your ServiceNow widget client controller:

 

// Assuming your form is named 'userForm' and the control you want to mark as dirty is 'first_name'
$scope.userForm.first_name.$setDirty();

 

 

This will mark the `first_name` control as dirty. Make sure that the form name (`userForm` in this example) matches the `name` attribute of your `<form>` element in the HTML template.

 

Here's a more complete example of how you might use it in your client controller:

 

api.controller = function($scope) {
    /* widget controller */
    var c = this;

    c.$onInit = function() {
        // Pre-populate your controls here
        c.first_name = "Pre-populated Value";

        // Now mark the control as dirty
        if ($scope.userForm && $scope.userForm.first_name) {
            $scope.userForm.first_name.$setDirty();
        }
    };
};

 

 

Make sure to replace `userForm` and `first_name` with the actual names of your form and input if they are different. Also, ensure that the `$onInit` function is called after the form has been initialized, otherwise the form control might not be available to mark as dirty.

Please mark this response as correct or helpful if it assisted you with your question.

View solution in original post

2 REPLIES 2

Iraj Shaikh
Mega Sage
Mega Sage

Hi @peter0611 

 

In AngularJS, which is typically used in ServiceNow widgets, you can interact with forms and their controls through the `$scope` object and the form directive. To mark a control as dirty, you would typically access the form and the control within your client controller and use the `$setDirty()` method on the control.

 

Here's how you can do it in your ServiceNow widget client controller:

 

// Assuming your form is named 'userForm' and the control you want to mark as dirty is 'first_name'
$scope.userForm.first_name.$setDirty();

 

 

This will mark the `first_name` control as dirty. Make sure that the form name (`userForm` in this example) matches the `name` attribute of your `<form>` element in the HTML template.

 

Here's a more complete example of how you might use it in your client controller:

 

api.controller = function($scope) {
    /* widget controller */
    var c = this;

    c.$onInit = function() {
        // Pre-populate your controls here
        c.first_name = "Pre-populated Value";

        // Now mark the control as dirty
        if ($scope.userForm && $scope.userForm.first_name) {
            $scope.userForm.first_name.$setDirty();
        }
    };
};

 

 

Make sure to replace `userForm` and `first_name` with the actual names of your form and input if they are different. Also, ensure that the `$onInit` function is called after the form has been initialized, otherwise the form control might not be available to mark as dirty.

Please mark this response as correct or helpful if it assisted you with your question.

Thanks, Iraj. Here is my updated code:

 

c.$onInit = function() {
		console.log($scope);

        // If there is existing data for the logged in user, prepopulate the form.
        c.first_name = c.data.cp_first_name ? c.data.cp_first_name : "";
        c.last_name = c.data.cp_last_name ? c.data.cp_last_name : "";
        // Since the input is type Date, create new Date object so it can be applied to the form input.
        c.dob = c.data.dob ? new Date(c.data.dob) : "";
        c.dcn = c.data.dcn ? c.data.dcn : "";

        // Set successfully pre-populated inputs to "dirty" state
        if (c.first_name && $scope.userForm && $scope.userForm.first_name) {
            $scope.userForm.first_name.$setDirty();

        }
    };

 

 In the function I logged the $scope object and it clearly shows that the userForm and first_name control property exists in it. See screenshot:

peter0611_1-1704301281160.png

 

 

But then the if statement to check that they are defined fails as if those properties don't exist. Quite confused.

 

Update: So... wrapping the code in the c.$onInit function into a setTimeout() function gave the HTML enough time to render everything. Your comment about making sure to only call once the form is fully initialized was correct!