diff --git a/docs/en_US/images/role_drop_dialog.png b/docs/en_US/images/role_drop_dialog.png
index 5114b7e522336d1a77063c8ba6111b2fd19f3e78..46871136b063b6a99c850a781991b2d9369832a5 100644
GIT binary patch
diff --git a/docs/en_US/images/role_drop_dialog_sql.png b/docs/en_US/images/role_drop_dialog_sql.png
index c541faa5fb6de7fd088751dbc609f390d259ff48..28e1f8a0cf217338b5bcd19f522edb0598abe6e2 100644
GIT binary patch
diff --git a/docs/en_US/images/role_reassign_dialog.png b/docs/en_US/images/role_reassign_dialog.png
index 53494f2e503a06637a9b2b355d12db73870dde56..fe37d140124c02818c880d16a8ee6029c74aef65 100644
GIT binary patch
diff --git a/docs/en_US/images/role_reassign_dialog_sql.png b/docs/en_US/images/role_reassign_dialog_sql.png
index 8f60f9c06aa7d58a8c4b9bcd163e1aca14961ddf..a09721668fe6cd2780788c04a7d1df67529eb016 100644
GIT binary patch
diff --git a/web/pgadmin/browser/server_groups/servers/roles/static/js/role.js b/web/pgadmin/browser/server_groups/servers/roles/static/js/role.js
index 0b037813c..97fd76339 100644
--- a/web/pgadmin/browser/server_groups/servers/roles/static/js/role.js
+++ b/web/pgadmin/browser/server_groups/servers/roles/static/js/role.js
@@ -10,7 +10,7 @@ import RoleSchema from './role.ui';
 import { getNodeVariableSchema } from '../../../static/js/variable.ui';
 import { getNodeListByName } from '../../../../../static/js/node_ajax';
 import { getMembershipSchema } from '../../../static/js/membership.ui';
-import Notify from '../../../../../../static/js/helpers/Notifier';
+import {showRoleReassignDialogue} from './roleReassign';
 
 define('pgadmin.node.role', [
   'sources/gettext', 'sources/url_for', 'jquery', 'underscore',
@@ -18,7 +18,7 @@ define('pgadmin.node.role', [
   'pgadmin.backform', 'axios', 'sources/utils', 'backbone', 'select2',
   'pgadmin.browser.collection', 'pgadmin.browser.node.ui',
   'pgadmin.browser.server.variable',
-], function(gettext, url_for, $, _, pgAdmin, pgBrowser, alertify, Backform, axios, utils, Backbone) {
+], function(gettext, url_for, $, _, pgAdmin, pgBrowser) {
 
   if (!pgBrowser.Nodes['coll-role']) {
     pgAdmin.Browser.Nodes['coll-role'] =
@@ -127,450 +127,7 @@ define('pgadmin.node.role', [
         return server.connected && node.can_login;
       },
       reassign_role: function() {
-
-        var tree = pgBrowser.tree,
-          _i = tree.selected(),
-          _d = _i ? tree.itemData(_i) : undefined,
-          obj = this, finalUrl, old_role_name;
-
-        //RoleReassign Model (Objects like role, database)
-        var RoleReassignObjectModel = Backbone.Model.extend({
-          idAttribute: 'id',
-          defaults: {
-            role_op: undefined,
-            did: undefined,
-            new_role_id: undefined,
-            new_role_name: undefined,
-            old_role_name: undefined,
-            drop_with_cascade: false
-          },
-
-          // Default values!
-          initialize: function() {
-            // Set default options according to node type selection by user
-            Backbone.Model.prototype.initialize.apply(this, arguments);
-          },
-          schema: [
-            {
-              id: 'role_op',
-              label: gettext('Operation'),
-              cell: 'string',
-              type: 'radioModern',
-              controlsClassName: 'pgadmin-controls col-12 col-sm-8',
-              controlLabelClassName: 'control-label col-sm-4 col-12',
-              group: gettext('General'),
-              options: [{
-                'label': 'Reassign',
-                'value': 'reassign',
-              },
-              {
-                'label': 'Drop',
-                'value': 'drop',
-              },
-              ],
-              helpMessage: gettext('Change the ownership or\ndrop the database objects owned by a database role'),
-            },
-            {
-              id: 'new_role_name',
-              label: gettext('Reassign objects to'),
-              controlsClassName: 'pgadmin-controls col-12 col-sm-8',
-              controlLabelClassName: 'control-label col-sm-4 col-12',
-              url: 'nodes',
-              helpMessage: gettext('New owner of the affected objects'),
-              transform: function(data, cell) {
-                var res = [],
-                  control = cell || this,
-                  node = control.field.get('schema_node');
-
-                // remove the current role from list
-                let current_label = control.field.attributes.node_info.role.label;
-                if (data && _.isArray(data)) {
-
-                  let CURRENT_USER = {
-                      label: 'CURRENT_USER', value: 'CURRENT_USER',
-                      image: 'icon-' + node.type, _id: null,
-                    },
-                    SESSION_USER = {
-                      label: 'SESSION_USER', value: 'SESSION_USER', image: 'icon-' + node.type, _id: null,
-                    };
-                  CURRENT_USER.value = JSON.stringify(CURRENT_USER);
-                  SESSION_USER.value = JSON.stringify(SESSION_USER);
-
-                  res.push(CURRENT_USER, SESSION_USER);
-
-                  if(control.field.attributes.node_data.version >= 140000) {
-                    let CURRENT_ROLE = {
-                      label: 'CURRENT_ROLE', value: 'CURRENT_ROLE',
-                      image: 'icon-' + node.type, _id: null,
-                    };
-                    CURRENT_ROLE.value = JSON.stringify(CURRENT_ROLE);
-                    res.push(CURRENT_ROLE);
-                  }
-
-                  _.each(data, function(d) {
-                    /*
-                      * d contains json data and sets into
-                      * select's option control
-                      *
-                      * We need to stringify data because formatter will
-                      * convert Array Object as [Object] string
-                      */
-                    if (current_label != d.label)
-                      res.push({label: d.label, image: d.icon, value: JSON.stringify(d)});
-                  });
-                }
-                return res;
-              },
-              control: Backform.NodeListByIdControl.extend({
-                getValueFromDOM: function() {
-                  var data = this.formatter.toRaw(
-                    _.unescape(this.$el.find('select').val()), this.model);
-                  /*
-                   * return null if data is empty to prevent it from
-                   * throwing parsing error. Adds check as name can be empty
-                   */
-                  if (data === '') {
-                    return null;
-                  }
-                  else if (typeof(data) === 'string') {
-                    data=JSON.parse(data);
-                  }
-                  return data.label;
-                },
-                /*
-                 * When name is changed, extract value from its select option and
-                 * set attributes values into the model
-                 */
-                onChange: function() {
-                  Backform.NodeAjaxOptionsControl.prototype.onChange.apply(
-                    this, arguments
-                  );
-                  var selectedValue = this.$el.find('select').val();
-                  if (selectedValue.trim() != '') {
-                    var d = this.formatter.toRaw(selectedValue, this.model);
-                    if(typeof(d) === 'string')
-                      d=JSON.parse(d);
-                    this.model.set({
-                      'new_role_id' : d._id,
-                      'new_role_name': d.label,
-                    });
-                  }
-                }
-              }),
-              node: 'role',
-              group: gettext('General'),
-              select2: {
-                allowClear: false,
-              },
-              disabled: 'isDisabled',
-              deps: ['role_op'],
-              filter: function(d) {
-                // Exclude the currently selected
-                let ltree = pgBrowser.tree,
-                  _idx = ltree.selected(),
-                  _data = _idx && _idx.length == 1 ? ltree.itemData(_idx) : undefined;
-
-                if(!_data)
-                  return true;
-
-                return d && (d.label != _data.label);
-              },
-            },
-            {
-              id: 'drop_with_cascade',
-              label: gettext('Cascade?'),
-              cell: 'string',
-              type: 'switch',
-              controlsClassName: 'pgadmin-controls col-12 col-sm-8',
-              controlLabelClassName: 'control-label col-sm-4 col-12',
-              disabled: 'isDisabled',
-              group: gettext('General'),
-              options: {
-                'onText':  gettext('Yes'),
-                'offText':  gettext('No'), 'size': 'mini'
-              },
-              deps: ['role_op'],
-              helpMessage: gettext('Note: CASCADE will automatically drop objects that depend on the affected objects, and in turn all objects that depend on those objects'),
-            },
-            {
-              id: 'did',
-              label: gettext('From database'),
-              controlsClassName: 'pgadmin-controls col-12 col-sm-8',
-              controlLabelClassName: 'control-label col-sm-4 col-12',
-              node: 'database',
-              group: gettext('General'),
-              disabled: 'isDisabled',
-              control: Backform.NodeListByIdControl.extend({
-                onChange: function() {
-                  Backform.NodeListByIdControl.prototype.onChange.apply(
-                    this, arguments
-                  );
-                  let did = this.model.get('did');
-                  this.model.set('did', parseInt(did));
-                },
-              }),
-              select2: {
-                allowClear: false,
-              },
-              events: {
-                'select2:select': 'onChange'
-              },
-              first_empty: false,
-              helpMessage: gettext('Target database on which the operation will be carried out'),
-            },
-            {
-              id: 'sqltab', label: gettext('SQL'), group: gettext('SQL'),
-              type: 'text', disabled: false, control: Backform.SqlTabControl.extend({
-                initialize: function() {
-                  // Initialize parent class
-                  Backform.SqlTabControl.prototype.initialize.apply(this, arguments);
-                },
-                onTabChange: function(sql_tab_obj) {
-                  // Fetch the information only if the SQL tab is visible at the moment.
-                  if (this.dialog && sql_tab_obj.shown == this.tabIndex) {
-                    var self = this,
-                      roleReassignData = self.model.toJSON(),
-                      getUrl;
-                    // Add existing role
-                    roleReassignData.old_role_name = old_role_name;
-
-                    getUrl = obj.generate_url(_i, 'reassign' , _d, true);
-
-                    $.ajax({
-                      url: getUrl,
-                      type: 'GET',
-                      cache: false,
-                      data: roleReassignData,
-                      dataType: 'json',
-                      contentType: 'application/json',
-                    }).done(function(res) {
-                      self.sqlCtrl.setValue(res.data);
-                    });
-                  }
-                },
-              }),
-            }
-          ],
-          validate: function() {
-            return null;
-          },
-          isDisabled: function(m) {
-
-            let self_local = this;
-            switch(this.name) {
-            case 'new_role_name':
-              return (m.get('role_op') != 'reassign');
-            case 'drop_with_cascade':
-              return (m.get('role_op') != 'drop');
-            case 'did':
-              setTimeout(function() {
-                if(_.isUndefined(m.get('did'))) {
-                  let db = self_local.options[0];
-                  m.set('did', db.value);
-                }
-              }, 10);
-              return false;
-            default:
-              return false;
-            }
-          },
-        });
-
-        if (!_d)
-          return;
-
-        if (!alertify.roleReassignDialog) {
-          alertify.dialog('roleReassignDialog', function factory() {
-            return {
-              main: function(title) {
-                this.set('title', title);
-              },
-              setup: function() {
-                return {
-                  buttons:[{
-                    text: '', key: 112,
-                    className: 'btn btn-primary-icon pull-left fa fa-question pg-alertify-icon-button',
-                    attrs:{name:'dialog_help', type:'button', label: gettext('Users'),
-                      url: url_for('help.static', {'filename': 'role_reassign_dialog.html'})},
-                  },{
-                    text: gettext('Cancel'),
-                    key: 27,
-                    className: 'btn btn-secondary fa fa-lg fa-times pg-alertify-button',
-                  }, {
-                    text: gettext('OK'),
-                    key: 13,
-                    className: 'btn btn-primary fa fa-lg fa-save pg-alertify-button',
-                  }],
-                  focus: {
-                    element: 0,
-                  },
-                  options: {
-                    //disable both padding and overflow control.
-                    padding : !1,
-                    overflow: !1,
-                    modal: false,
-                    resizable: true,
-                    maximizable: true,
-                    pinnable: false,
-                    closableByDimmer: false,
-                  },
-                };
-              },
-              build: function() {
-                alertify.pgDialogBuild.apply(this);
-              },
-              hooks:{
-                onclose: function() {
-                  if (this.view) {
-                    // clear our backform model/view
-                    this.view.remove({data: true, internal: true, silent: true});
-                  }
-                },
-              },
-              prepare:function() {
-
-                var self = this,
-                  $container = $('<div class=\'role_reassign_own\'></div>');
-                //Disable Okay button
-                self.__internal.buttons[2].element.disabled = true;
-                // Find current/selected node
-                var ltree = pgBrowser.tree,
-                  _idx = ltree.selected(),
-                  _data = _idx ? ltree.itemData(_idx) : undefined,
-                  node = _data && pgBrowser.Nodes[_data._type];
-
-                finalUrl = obj.generate_url(_idx, 'reassign' , _data, true);
-                old_role_name = _data.label;
-
-                if (!_data)
-                  return;
-                // Create treeInfo
-                var treeInfo = pgBrowser.tree.getTreeNodeHierarchy(_idx);
-                // Instance of backbone model
-                var newModel = new RoleReassignObjectModel({}, {node_info: treeInfo}),
-                  fields = Backform.generateViewSchema(
-                    treeInfo, newModel, 'create', node,
-                    treeInfo.server, true
-                  );
-
-                var view = self.view = new Backform.Dialog({
-                  el: $container, model: newModel, schema: fields,
-                });
-                // Add our class to alertify
-                $(self.elements.body.childNodes[0]).addClass(
-                  'alertify_tools_dialog_properties obj_properties'
-                );
-
-                // Render dialog
-                view.render();
-                self.elements.content.append($container.get(0));
-
-                const statusBar = $(
-                  '<div class=\'pg-prop-status-bar pg-prop-status-bar-absolute pg-el-xs-12 d-none\'>' +
-                  '  <div class="error-in-footer"> ' +
-                  '    <div class="d-flex px-2 py-1"> ' +
-                  '      <div class="pr-2"> ' +
-                  '        <i class="fa fa-exclamation-triangle text-danger" aria-hidden="true"></i> ' +
-                  '      </div> ' +
-                  '      <div class="alert-text" role="alert"></div> ' +
-                  '       <div class="ml-auto close-error-bar"> ' +
-                  '          <a aria-label="' + gettext('Close error bar') + '" class="close-error fa fa-times text-danger"></a> ' +
-                  '        </div> ' +
-                  '    </div> ' +
-                  '  </div> ' +
-                  '</div>').appendTo($container);
-
-                // Listen to model & if filename is provided then enable Backup button
-                this.view.model.on('change', function() {
-
-                  const ctx = this;
-
-                  const showError = function(errorField, errormsg) {
-                    ctx.errorModel.set(errorField, errormsg);
-                    statusBar.removeClass('d-none');
-                    statusBar.find('.alert-text').html(errormsg);
-                    self.elements.dialog.querySelector('.close-error').addEventListener('click', ()=>{
-                      statusBar.addClass('d-none');
-                      ctx.errorModel.set(errorField, errormsg);
-                    });
-                  };
-                  statusBar.addClass('d-none');
-
-                  if ((this.get('role_op') == 'reassign')
-                    && !_.isUndefined(this.get('new_role_name')
-                    && this.get('new_role_name') !== '')
-                  ) {
-                    this.errorModel.clear();
-                    self.__internal.buttons[2].element.disabled = false;
-                  } else if(this.get('role_op') == 'drop') {
-                    this.errorModel.clear();
-                    this.set({'new_role_name': undefined, silent: true});
-                    this.set({'new_role_id': undefined, silent: true});
-                    self.__internal.buttons[2].element.disabled = false;
-                  } else if(_.isUndefined(this.get('new_role_name'))) {
-                    let errmsg = gettext('Please provide a new role name');
-                    this.errorModel.set('new_role_name', errmsg);
-                    showError('new_role_name', errmsg);
-                    self.__internal.buttons[2].element.disabled = true;
-                  }
-                  else {
-                    self.__internal.buttons[2].element.disabled = true;
-                  }
-                });
-
-                // set default role operation as reassign
-                this.view.model.set({'role_op': 'reassign'});
-              },
-              // Callback functions when click on the buttons of the alertify dialogs
-              callback: function(e) {
-                if (e.button.element.name == 'dialog_help') {
-                  e.cancel = true;
-                  pgBrowser.showHelp(e.button.element.name, e.button.element.getAttribute('url'),
-                    null, null);
-                  return;
-                }
-                if (e.button.text === gettext('OK')) {
-
-                  let roleReassignData = this.view.model.toJSON(),
-                    roleOp = roleReassignData.role_op,
-                    confirmBoxTitle = utils.titleize(roleOp);
-
-                  Notify.confirm(
-                    gettext('%s Objects', confirmBoxTitle),
-                    gettext('Are you sure you wish to %s all the objects owned by the selected role?', roleOp),
-                    function() {
-                      axios.post(
-                        finalUrl,
-                        roleReassignData
-                      ).then(function (response) {
-                        if(response.data)
-                          Notify.success(response.data.info);
-                      }).catch(function (error) {
-                        try {
-                          const err = error.response.data;
-                          Notify.alert(
-                            gettext('Role reassign/drop failed.'),
-                            err.errormsg
-                          );
-                        } catch (ex) {
-                          console.warn(ex.stack || ex);
-                        }
-                      });
-                    },
-                    function() { return true; }
-                  ).set('labels', {
-                    ok: gettext('Yes'),
-                    cancel: gettext('No'),
-                  });
-                }
-              },
-            };
-          });
-        }
-
-        alertify.roleReassignDialog(
-          gettext('Reassign/Drop Owned - \'%s\'', _d.label)
-        ).resizeTo(pgAdmin.Browser.stdW.md, pgAdmin.Browser.stdH.lg);
+        showRoleReassignDialogue();
       },
       getSchema: function(treeNodeInfo, itemNodeData) {
         return new RoleSchema(
diff --git a/web/pgadmin/browser/server_groups/servers/roles/static/js/roleReassign.js b/web/pgadmin/browser/server_groups/servers/roles/static/js/roleReassign.js
new file mode 100644
index 000000000..d0dc81068
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/roles/static/js/roleReassign.js
@@ -0,0 +1,234 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2022, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+
+import gettext from 'sources/gettext';
+import BaseUISchema from 'sources/SchemaView/base_schema.ui';
+import url_for from 'sources/url_for';
+import { getNodeListByName, generateNodeUrl } from '../../../../../static/js/node_ajax';
+import pgBrowser from 'top/browser/static/js/browser';
+import {getUtilityView} from '../../../../../static/js/utility_view';
+import Notify from '../../../../../../static/js/helpers/Notifier';
+import { isEmptyString } from 'sources/validators';
+import pgAdmin from 'sources/pgadmin';
+
+export default class RoleReassign extends BaseUISchema{
+  constructor(fieldOptions={}, initValues={}){
+    super({
+      role_op: 'reassign',
+      did: undefined,
+      new_role_id: undefined,
+      new_role_name: undefined,
+      drop_with_cascade: false,
+      old_role_name: initValues.old_role_name,
+      ...initValues
+    });
+
+    this.fieldOptions = {
+      roleList: fieldOptions.roleList,
+      databaseList: fieldOptions.databaseList,
+      nodeInfo: fieldOptions.nodeInfo,
+      ...fieldOptions,
+    };
+
+    this.nodeInfo = this.fieldOptions.nodeInfo;
+    this.warningText = null;
+  }
+
+  get idAttribute() {
+    return 'oid';
+  }
+
+  get baseFields(){
+    let obj = this;
+    return [
+      {
+        id: 'role_op',
+        label: gettext('Operation'),
+        group: gettext('General'),
+        type: 'toggle',
+        options: [
+          { 'label': gettext('Reassign'), 'value': 'reassign' },
+          { 'label': gettext('Drop'), 'value': 'drop' },
+        ],
+        helpMessage: gettext('Change the ownership or\ndrop the database objects owned by a database role')
+      },
+      {
+        id: 'new_role_id',
+        label: gettext('Reassign objects to'),
+        group: gettext('General'),
+        type: ()=>{
+          return{
+            type: 'select',
+            options: this.fieldOptions.roleList,
+            optionsLoaded: (options) => { obj.roleNameIdList = options; },
+            controlProps: {
+              allowClear: false,
+              filter: (options)=>{
+                let data = [];
+                let CURRENT_USER = {
+                    label: 'CURRENT_USER', value: 'CURRENT_USER', image: 'icon-role'
+                  },
+                  SESSION_USER = {
+                    label: 'SESSION_USER', value: 'SESSION_USER', image: 'icon-role'
+                  };
+                data.push(CURRENT_USER, SESSION_USER);
+
+                if (obj.getServerVersion() >= 140000){
+                  let CURRENT_ROLE = {
+                    label: 'CURRENT_ROLE', value: 'CURRENT_ROLE', image: 'icon-role'
+                  };
+                  data.push(CURRENT_ROLE);
+                }
+                if (options && _.isArray(options)){
+                  _.each(options, function(d) {
+                  // omit currently selected role
+                    if(d._id != obj.nodeInfo.role._id){
+                      data.push({label: d.label, value: d._id, image: d.image});
+                    }
+                  });
+                }
+                return data;
+              }
+            }
+          };
+        },
+        helpMessage: gettext('New owner of the affected objects'),
+        deps: ['role_op'],
+        disabled: (state)=>{
+          return state.role_op == 'drop'? true: false;
+        },
+        depChange: (state) =>{
+          if (state.role_op == 'drop'){
+            return {new_role_id:''};
+          }
+        }
+      },
+      { /* this is dummy field not shown on UI but added as API require this value */
+        id: 'new_role_name',
+        visible: false,
+        type: '',
+        deps:['new_role_id'],
+        depChange: (state)=>{
+          let new_role_name;
+          if (['CURRENT_USER','SESSION_USER','CURRENT_ROLE'].includes(state.new_role_id)){
+            new_role_name = state.new_role_id;
+          }else{
+            new_role_name = obj.roleNameIdList.find(o=> o._id === state.new_role_id).label;
+          }
+          return {new_role_name: new_role_name};
+        }
+      },
+      {
+        id: 'drop_with_cascade',
+        label: gettext('Cascade?'),
+        group: gettext('General'),
+        type: 'switch',
+        deps: ['role_op'],
+        helpMessage: gettext('Note: CASCADE will automatically drop objects that depend on the affected objects, and in turn all objects that depend on those objects')
+      },
+      {
+        id: 'did',
+        label: gettext('From database'),
+        group: gettext('General'),
+        helpMessage: gettext('Target database on which the operation will be carried out'),
+        type: ()=>{
+          return {
+            type: 'select',
+            options: this.fieldOptions.databaseList,
+            controlProps: {
+              allowClear: false,
+              filter: (options)=>{
+                let data = [];
+                if (options && _.isArray(options)){
+                  _.each(options, function(d) {
+                    data.push({label: d.label, value: d._id, image: d.image});
+                  });
+                }
+                return data;
+              }
+            },
+          };
+        }
+      }
+    ];
+  }
+
+  validate(state, setError) {
+    let errmsg = null;
+    let obj = this;
+    if(state.role_op == 'reassign' && isEmptyString(state.new_role_id)){
+      errmsg = gettext('\'Reassign objects to\' can not be empty');
+      setError('new_role_id', errmsg);
+      return true;
+    }
+    if(isEmptyString(state.did)){
+      errmsg = gettext('\'From database \' can not be empty');
+      setError('did', errmsg);
+      return true;
+    }
+    obj.warningText = gettext(`Are you sure you wish to ${state.role_op} all the objects owned by the selected role?`);
+    return false;
+  }
+}
+
+function saveCallBack (data) {
+  if(data.errormsg) {
+    Notify.alert(
+      gettext('Error'),
+      gettext(data.errormsg)
+    );
+  } else {
+    Notify.success(gettext(data.info));
+  }
+}
+
+function getUISchema(treeNodeInfo, itemNodeData ){
+  return new RoleReassign(
+    {
+      roleList: ()=>getNodeListByName('role', treeNodeInfo, itemNodeData, {includeItemKeys: ['_id']}),
+      databaseList: ()=>getNodeListByName('database', treeNodeInfo, itemNodeData, {cacheLevel: 'database', cacheNode: 'database', includeItemKeys: ['_id']}),
+      nodeInfo: treeNodeInfo
+    },
+    {
+      old_role_name: itemNodeData.label
+    }
+  );
+}
+
+export function showRoleReassignDialogue(){
+  var tree = pgBrowser.tree,
+    item = tree.selected(),
+    data = item ? tree.itemData(item) : undefined;
+
+  let treeNodeInfo = pgBrowser.tree.getTreeNodeHierarchy(item);
+  let itemNodeData = pgBrowser.tree.findNodeByDomElement(item).getData();
+
+  pgBrowser.Node.registerUtilityPanel();
+  var panel = pgBrowser.Node.addUtilityPanel(pgBrowser.stdW.md),
+    j = panel.$container.find('.obj_properties').first();
+
+  var schema = getUISchema(treeNodeInfo, itemNodeData);
+
+  panel.title(gettext(`Reassign/Drop Owned - ${data.label}`));
+  panel.focus();
+
+  const baseUrl = generateNodeUrl.call( pgAdmin.Browser.Nodes[data._type], treeNodeInfo, 'reassign', data, true);
+
+  let sqlHelpUrl = '',
+    helpUrl = url_for('help.static', {
+      'filename': 'role_reassign_dialog.html',
+    });
+
+  let msqlurl = generateNodeUrl.call( pgAdmin.Browser.Nodes[data._type], treeNodeInfo, 'reassign', data, true);
+
+  let extraData = {nodeType: data._type, msqlurl:msqlurl};
+
+  getUtilityView(
+    schema, treeNodeInfo, 'create', 'dialog', j[0], panel, saveCallBack, extraData, 'Reassign/Drop', baseUrl, sqlHelpUrl, helpUrl);
+}
\ No newline at end of file
diff --git a/web/pgadmin/browser/static/js/utility_view.jsx b/web/pgadmin/browser/static/js/utility_view.jsx
index 296ddfdbf..19250c2f4 100644
--- a/web/pgadmin/browser/static/js/utility_view.jsx
+++ b/web/pgadmin/browser/static/js/utility_view.jsx
@@ -16,6 +16,7 @@ import SchemaView from 'sources/SchemaView';
 import 'wcdocker';
 import Theme from '../../../static/js/Theme';
 import url_for from 'sources/url_for';
+import { generateNodeUrl } from './node_ajax';
 
 /* The entry point for rendering React based view in properties, called in node.js */
 export function getUtilityView(schema, treeNodeInfo, actionType, formType, container, containerPanel,
@@ -33,6 +34,10 @@ export function getUtilityView(schema, treeNodeInfo, actionType, formType, conta
   /* button icons */
   const saveBtnIcon = extraData.save_btn_icon;
 
+  /* Node type & Noen obj*/
+  let nodeObj = extraData.nodeType? pgAdmin.Browser.Nodes[extraData.nodeType]: undefined;
+  let itemNodeData = extraData?.itemNodeData ? itemNodeData: undefined;
+
   /* on save button callback, promise required */
   const onSaveClick = (isNew, data)=>new Promise((resolve, reject)=>{
     return api({
@@ -49,6 +54,23 @@ export function getUtilityView(schema, treeNodeInfo, actionType, formType, conta
     });
   });
 
+  /* Called when switched to SQL tab, promise required */
+  const getSQLValue = (isNew, changedData)=>{
+    const msqlUrl = extraData?.msqlurl ? extraData.msqlurl: generateNodeUrl.call(nodeObj, treeNodeInfo, 'msql', itemNodeData, !isNew, nodeObj.url_jump_after_node);
+    return new Promise((resolve, reject)=>{
+      api({
+        url: msqlUrl,
+        method: 'GET',
+        params: changedData,
+      }).then((res)=>{
+        resolve(res.data.data);
+      }).catch((err)=>{
+        onError(err);
+        reject(err);
+      });
+    });
+  };
+
   /* Callback for help button */
   const onHelp = (isSqlHelp=false)=>{
     if(isSqlHelp) {
@@ -100,6 +122,15 @@ export function getUtilityView(schema, treeNodeInfo, actionType, formType, conta
 
   });
 
+  let onError = (err)=> {
+    if(err.response){
+      console.error('error resp', err.response);
+    } else if(err.request){
+      console.error('error req', err.request);
+    } else if(err.message){
+      console.error('error msg', err.message);
+    }
+  };
   let _schema = schema;
 
   /* Fire at will, mount the DOM */
@@ -117,7 +148,8 @@ export function getUtilityView(schema, treeNodeInfo, actionType, formType, conta
         onHelp={onHelp}
         onDataChange={()=>{/*This is intentional (SonarQube)*/}}
         confirmOnCloseReset={confirmOnReset}
-        hasSQL={false}
+        hasSQL={nodeObj?nodeObj.hasSQL:false && (actionType === 'create' || actionType === 'edit')}
+        getSQLValue={getSQLValue}
         isTabView={isTabView}
         disableSqlHelp={sqlHelpUrl == undefined || sqlHelpUrl == ''}
         disableDialogHelp={helpUrl == undefined || helpUrl == ''}
