diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py
index c4b023eea..154a17bb8 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py
@@ -1480,7 +1480,8 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
         parallel_dict = {'u': 'UNSAFE', 's': 'SAFE', 'r': 'RESTRICTED'}
 
         # Get Schema Name from its OID.
-        self._get_schema_name_from_oid(data)
+        if self.node_type != 'trigger_function':
+            self._get_schema_name_from_oid(data)
 
         if fnid is not None:
             # Edit Mode
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/trigger_function.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/trigger_function.js
index 94d9e9a7b..83ed9c6e3 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/trigger_function.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/trigger_function.js
@@ -6,6 +6,10 @@
 // This software is released under the PostgreSQL Licence
 //
 //////////////////////////////////////////////////////////////
+import TriggerFunctionSchema from './trigger_function.ui';
+import { getNodeListByName, getNodeAjaxOptions } from '../../../../../../../static/js/node_ajax';
+import { getNodeVariableSchema } from '../../../../../static/js/variable.ui';
+import { getNodePrivilegeRoleSchema } from '../../../../../static/js/privilege.ui';
 
 /* Create and Register Function Collection and Node. */
 define('pgadmin.node.trigger_function', [
@@ -81,6 +85,26 @@ define('pgadmin.node.trigger_function', [
         },
         ]);
       },
+      getSchema: function(treeNodeInfo, itemNodeData) {
+        return new TriggerFunctionSchema(
+          (privileges)=>getNodePrivilegeRoleSchema('', treeNodeInfo, itemNodeData, privileges),
+          ()=>getNodeVariableSchema(this, treeNodeInfo, itemNodeData, false, false),
+          {
+            role: ()=>getNodeListByName('role', treeNodeInfo, itemNodeData),
+            schema: ()=>getNodeListByName('schema', treeNodeInfo, itemNodeData, {cacheLevel: 'database'}),
+            language: ()=>getNodeAjaxOptions('get_languages', this, treeNodeInfo, itemNodeData, {noCache: true}, (res) => {
+              return _.reject(res, function(o) {
+                return o.label == 'sql' || o.label == 'edbspl';
+              });
+            }),
+            nodeInfo: treeNodeInfo
+          },
+          {
+            funcowner: pgBrowser.serverInfo[treeNodeInfo.server._id].user.name,
+            pronamespace: treeNodeInfo.schema ? treeNodeInfo.schema.label : ''
+          }
+        );
+      },
       model: pgBrowser.Node.Model.extend({
         idAttribute: 'oid',
         initialize: function(attrs, args) {
@@ -99,34 +123,8 @@ define('pgadmin.node.trigger_function', [
         defaults: {
           name: undefined,
           oid: undefined,
-          xmin: undefined,
           funcowner: undefined,
-          pronamespace: undefined,
           description: undefined,
-          pronargs: undefined, /* Argument Count */
-          proargs: undefined, /* Arguments */
-          proargtypenames: undefined, /* Argument Signature */
-          prorettypename: 'trigger', /* Return Type */
-          lanname: 'plpgsql', /* Language Name in which function is being written */
-          provolatile: undefined, /* Volatility */
-          proretset: undefined, /* Return Set */
-          proisstrict: undefined,
-          prosecdef: undefined, /* Security of definer */
-          proiswindow: undefined, /* Window Function ? */
-          procost: undefined, /* Estimated execution Cost */
-          prorows: undefined, /* Estimated number of rows */
-          proleakproof: undefined,
-          args: [],
-          prosrc: undefined,
-          prosrc_c: undefined,
-          probin: '$libdir/',
-          options: [],
-          variables: [],
-          proacl: undefined,
-          seclabels: [],
-          acl: [],
-          sysfunc: undefined,
-          sysproc: undefined,
         },
         schema: [{
           id: 'name', label: gettext('Name'), cell: 'string',
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/trigger_function.ui.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/trigger_function.ui.js
new file mode 100644
index 000000000..0257ce8b0
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/trigger_function.ui.js
@@ -0,0 +1,291 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2021, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+
+import gettext from 'sources/gettext';
+import SecLabelSchema from '../../../../../static/js/sec_label.ui';
+import BaseUISchema from 'sources/SchemaView/base_schema.ui';
+import { isEmptyString } from 'sources/validators';
+
+
+export default class TriggerFunctionSchema extends BaseUISchema {
+  constructor(getPrivilegeRoleSchema, getVariableSchema, fieldOptions={}, initValues) {
+    super({
+      name: null,
+      oid: null,
+      xmin: null,
+      funcowner: null,
+      pronamespace: null,
+      description: null,
+      pronargs: null, /* Argument Count */
+      proargs: null, /* Arguments */
+      proargtypenames: null, /* Argument Signature */
+      prorettypename: 'trigger', /* Return Type */
+      lanname: 'plpgsql', /* Language Name in which function is being written */
+      provolatile: null, /* Volatility */
+      proretset: null, /* Return Set */
+      proisstrict: null,
+      prosecdef: null, /* Security of definer */
+      proiswindow: null, /* Window Function ? */
+      procost: null, /* Estimated execution Cost */
+      prorows: null, /* Estimated number of rows */
+      proleakproof: null,
+      args: [],
+      prosrc: null,
+      prosrc_c: null,
+      probin: '$libdir/',
+      options: [],
+      variables: [],
+      proacl: null,
+      seclabels: [],
+      acl: [],
+      sysfunc: null,
+      sysproc: null,
+      ...initValues
+    });
+
+    this.getPrivilegeRoleSchema = getPrivilegeRoleSchema;
+    this.getVariableSchema = getVariableSchema;
+    this.fieldOptions = {
+      role: [],
+      schema: [],
+      language: [],
+      nodeInfo: null,
+      ...fieldOptions,
+    };
+
+  }
+
+  get idAttribute() {
+    return 'oid';
+  }
+
+  isReadonly(state) {
+    switch(state.name){
+    case 'proargs':
+    case 'proargtypenames':
+    case 'prorettypename':
+    case 'proretset':
+    case 'proiswindow':
+      return !this.isNew();
+    default:
+      return false;
+    }
+  }
+
+  isVisible(state) {
+    if (state.name == 'sysproc') { return false; }
+    return true;
+  }
+
+  isDisabled() {
+    if('catalog' in this.fieldOptions.nodeInfo) {
+      return true;
+    }
+    return false;
+  }
+
+
+  get baseFields() {
+    let obj = this;
+    return [
+      {
+        id: 'name', label: gettext('Name'), cell: 'text',
+        type: 'text', mode: ['properties', 'create', 'edit'],
+        disabled: obj.isDisabled, readonly: obj.isReadonly,
+        noEmpty: true
+      },{
+        id: 'oid', label: gettext('OID'), cell: 'text',
+        type: 'text' , mode: ['properties'],
+      },{
+        id: 'funcowner', label: gettext('Owner'), cell: 'text',
+        type:'select', disabled: obj.isDisabled, readonly: obj.isReadonly,
+        options: obj.fieldOptions.role,
+        controlProps: { allowClear: false }
+      },{
+        id: 'pronamespace', label: gettext('Schema'), cell: 'string',
+        type: 'select', cache_level: 'database',
+        disabled: obj.isDisabled, readonly: obj.isReadonly,
+        mode: ['create', 'edit'],
+        options: obj.fieldOptions.schema,
+        controlProps: { allowClear: false }
+      },{
+        id: 'sysfunc', label: gettext('System trigger function?'),
+        cell:'boolean', type: 'switch',
+        mode: ['properties'], visible: obj.isVisible
+      },{
+        id: 'sysproc', label: gettext('System procedure?'),
+        cell:'boolean', type: 'switch',
+        mode: ['properties'], visible: obj.isVisible
+      },{
+        id: 'description', label: gettext('Comment'), cell: 'string',
+        type: 'multiline', disabled: obj.isDisabled, readonly: obj.isReadonly,
+      },{
+        id: 'pronargs', label: gettext('Argument count'), cell: 'text',
+        type: 'text', group: gettext('Definition'), mode: ['properties'],
+      },{
+        id: 'proargs', label: gettext('Arguments'), cell: 'string',
+        type: 'text', group: gettext('Definition'), mode: ['properties', 'edit'],
+        ddisabled: obj.isDisabled, readonly: obj.isReadonly,
+      },{
+        id: 'proargtypenames', label: gettext('Signature arguments'), cell:
+        'text', type: 'text', group: gettext('Definition'), mode: ['properties'],
+        disabled: obj.isDisabled, readonly: obj.isReadonly,
+      },{
+        id: 'prorettypename', label: gettext('Return type'), cell: 'text',
+        type: 'select', group: gettext('Definition'),
+        disabled: obj.isDisabled, readonly: obj.isReadonly,
+        controlProps: {
+          width: '100%',
+          allowClear: false,
+        },
+        mode: ['create'], visible: obj.isVisible,
+        options: [
+          {label: gettext('trigger'), value: 'trigger'},
+          {label: gettext('event_trigger'), value: 'event_trigger'},
+        ],
+      },{
+        id: 'prorettypename', label: gettext('Return type'), cell: 'text',
+        type: 'text', group: gettext('Definition'),
+        mode: ['properties', 'edit'], disabled: obj.isDisabled, readonly: obj.isReadonly,
+        visible: obj.isVisible
+      },  {
+        id: 'lanname', label: gettext('Language'), cell: 'text',
+        type: 'select', group: gettext('Definition'),
+        disabled: obj.isDisabled, readonly: obj.isReadonly,
+        options: obj.fieldOptions.language,
+        controlProps: {
+          allowClear: false,
+          filter: (options) => {
+            return (options||[]).filter(option => {
+              return option.label != '';
+            });
+          }
+        },
+      },{
+        id: 'prosrc', label: gettext('Code'), cell: 'text',
+        type: 'sql', isFullTab: true,
+        mode: ['properties', 'create', 'edit'],
+        group: gettext('Code'), deps: ['lanname'],
+        visible: (state) => {
+          if (state.lanname == 'c') {
+            return false;
+          }
+          return true;
+        },
+        disabled: obj.isDisabled, readonly: obj.isReadonly,
+      },{
+        id: 'probin', label: gettext('Object file'), cell: 'string',
+        type: 'text', group: gettext('Definition'), deps: ['lanname'],
+        visible: (state) => {
+          if (state.lanname == 'c') { return true; }
+          return false;
+        },
+        disabled: obj.isDisabled, readonly: obj.isReadonly,
+      },{
+        id: 'prosrc_c', label: gettext('Link symbol'), cell: 'string',
+        type: 'text', group: gettext('Definition'),  deps: ['lanname'],
+        visible: (state) => {
+          if (state.lanname == 'c') { return true; }
+          return false;
+        },
+        disabled: obj.isDisabled, readonly: obj.isReadonly,
+      },{
+        id: 'provolatile', label: gettext('Volatility'), cell: 'text',
+        type: 'select', group: gettext('Options'),
+        options:[
+          {'label': 'VOLATILE', 'value': 'v'},
+          {'label': 'STABLE', 'value': 's'},
+          {'label': 'IMMUTABLE', 'value': 'i'},
+        ], disabled: obj.isDisabled, readonly: obj.isReadonly,
+        controlProps: { allowClear: false },
+      },{
+        id: 'proretset', label: gettext('Returns a set?'), type: 'switch',
+        group: gettext('Options'), disabled: obj.isDisabled, readonly: obj.isReadonly,
+        visible: obj.isVisible
+      },{
+        id: 'proisstrict', label: gettext('Strict?'), type: 'switch',
+        disabled: obj.isDisabled, readonly: obj.isReadonly, group: gettext('Options'),
+      },{
+        id: 'prosecdef', label: gettext('Security of definer?'),
+        group: gettext('Options'), cell:'boolean', type: 'switch',
+        disabled: obj.isDisabled, readonly: obj.isReadonly,
+      },{
+        id: 'proiswindow', label: gettext('Window?'),
+        group: gettext('Options'), cell:'boolean', type: 'switch',
+        disabled: obj.isDisabled, readonly: obj.isReadonly, visible: obj.isVisible
+      },{
+        id: 'procost', label: gettext('Estimated cost'), type: 'text',
+        group: gettext('Options'), disabled: obj.isDisabled, readonly: obj.isReadonly,
+      },{
+        id: 'prorows', label: gettext('Estimated rows'), type: 'text',
+        group: gettext('Options'),
+        disabled: (state) => {
+          let isDisabled = true;
+          if(state.proretset == true) {
+            isDisabled = false;
+          }
+          return isDisabled;
+        },
+        readonly: obj.isReadonly,
+        deps: ['proretset'], visible: obj.isVisible
+      },{
+        id: 'proleakproof', label: gettext('Leak proof?'),
+        group: gettext('Options'), cell:'boolean', type: 'switch', min_version: 90200,
+        disabled: obj.isDisabled, readonly: obj.isReadonly,
+      }, {
+        id: 'proacl', label: gettext('Privileges'), mode: ['properties'],
+        group: gettext('Security'), type: 'text',
+      },
+      {
+        id: 'variables', label: '', type: 'collection',
+        group: gettext('Parameters'), control: 'variable-collection',
+        mode: ['edit', 'create'], canEdit: false,
+        canDelete: true, disabled: obj.isDisabled, readonly: obj.isReadonly,
+        schema: this.getVariableSchema(),
+        editable: false,
+      },
+      {
+        id: 'acl', label: gettext('Privileges'), type: 'collection',
+        schema: this.getPrivilegeRoleSchema(['X']),
+        uniqueCol : ['grantee'],
+        editable: false,
+        group: gettext('Security'), mode: ['edit', 'create'],
+        canAdd: true, canDelete: true,
+      },
+      {
+        id: 'seclabels', label: gettext('Security labels'), type: 'collection',
+        schema: new SecLabelSchema(),
+        editable: false, group: gettext('Security'),
+        mode: ['edit', 'create'],
+        canAdd: true, canEdit: false, canDelete: true,
+        uniqueCol : ['provider'],
+        min_version: 90200,
+        disabled: obj.isDisabled, readonly: obj.isReadonly,
+      }
+    ];
+  }
+
+  validate(state, setError) {
+    let errmsg = null;
+
+    if (isEmptyString(state.service)) {
+
+      /* code validation*/
+      if (isEmptyString(state.prosrc)) {
+        errmsg = gettext('Code cannot be empty.');
+        setError('prosrc', errmsg);
+        return true;
+      } else {
+        errmsg = null;
+        setError('prosrc', errmsg);
+      }
+
+    }
+  }
+}
diff --git a/web/regression/javascript/schema_ui_files/trigger_function.ui.spec.js b/web/regression/javascript/schema_ui_files/trigger_function.ui.spec.js
new file mode 100644
index 000000000..a552d5d22
--- /dev/null
+++ b/web/regression/javascript/schema_ui_files/trigger_function.ui.spec.js
@@ -0,0 +1,126 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2021, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+
+import jasmineEnzyme from 'jasmine-enzyme';
+import React from 'react';
+import '../helper/enzyme.helper';
+import { createMount } from '@material-ui/core/test-utils';
+import pgAdmin from 'sources/pgadmin';
+import {messages} from '../fake_messages';
+import SchemaView from '../../../pgadmin/static/js/SchemaView';
+import BaseUISchema from 'sources/SchemaView/base_schema.ui';
+import TriggerFunctionSchema from '../../../pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/trigger_function.ui';
+
+class MockSchema extends BaseUISchema {
+  get baseFields() {
+    return [];
+  }
+}
+
+describe('TriggerFunctionSchema', ()=>{
+  let mount;
+  let schemaObj = new TriggerFunctionSchema(
+    ()=>new MockSchema(),
+    ()=>new MockSchema(),
+    {
+      role: [],
+      schema: [],
+      language: [],
+      nodeInfo: {}
+    },
+    {
+      funcowner: 'postgres',
+      pronamespace: 'public'
+    }
+  );
+  let getInitData = ()=>Promise.resolve({});
+
+  /* Use createMount so that material ui components gets the required context */
+  /* https://material-ui.com/guides/testing/#api */
+  beforeAll(()=>{
+    mount = createMount();
+  });
+
+  afterAll(() => {
+    mount.cleanUp();
+  });
+
+  beforeEach(()=>{
+    jasmineEnzyme();
+    /* messages used by validators */
+    pgAdmin.Browser = pgAdmin.Browser || {};
+    pgAdmin.Browser.messages = pgAdmin.Browser.messages || messages;
+    pgAdmin.Browser.utils = pgAdmin.Browser.utils || {};
+  });
+
+  it('create', ()=>{
+    mount(<SchemaView
+      formType='dialog'
+      schema={schemaObj}
+      viewHelperProps={{
+        mode: 'create',
+      }}
+      onSave={()=>{}}
+      onClose={()=>{}}
+      onHelp={()=>{}}
+      onEdit={()=>{}}
+      onDataChange={()=>{}}
+      confirmOnCloseReset={false}
+      hasSQL={false}
+      disableSqlHelp={false}
+    />);
+  });
+
+  it('edit', ()=>{
+    mount(<SchemaView
+      formType='dialog'
+      schema={schemaObj}
+      getInitData={getInitData}
+      viewHelperProps={{
+        mode: 'edit',
+      }}
+      onSave={()=>{}}
+      onClose={()=>{}}
+      onHelp={()=>{}}
+      onEdit={()=>{}}
+      onDataChange={()=>{}}
+      confirmOnCloseReset={false}
+      hasSQL={false}
+      disableSqlHelp={false}
+    />);
+  });
+
+  it('properties', ()=>{
+    mount(<SchemaView
+      formType='tab'
+      schema={schemaObj}
+      getInitData={getInitData}
+      viewHelperProps={{
+        mode: 'properties',
+      }}
+      onHelp={()=>{}}
+      onEdit={()=>{}}
+    />);
+  });
+
+  it('validate', ()=>{
+    let state = {};
+    let setError = jasmine.createSpy('setError');
+
+    state.prosrc = null;
+    schemaObj.validate(state, setError);
+    expect(setError).toHaveBeenCalledWith('prosrc', 'Code cannot be empty.');
+
+    state.prosrc = 'SELECT 1';
+    schemaObj.validate(state, setError);
+    expect(setError).toHaveBeenCalledWith('prosrc', null);
+  });
+
+});
+
