diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js
index ad5d7b2ec..ce36dde36 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js
@@ -7,6 +7,11 @@
 //
 //////////////////////////////////////////////////////////////
 
+import MViewSchema from './mview.ui';
+import { getNodeListByName } from '../../../../../../../static/js/node_ajax';
+import { getNodePrivilegeRoleSchema } from '../../../../../static/js/privilege.ui';
+import { getNodeVacuumSettingsSchema } from '../../../../../static/js/vacuum.ui';
+
 define('pgadmin.node.mview', [
   'sources/gettext', 'sources/url_for', 'jquery', 'underscore',
   'sources/pgadmin', 'pgadmin.alertifyjs', 'pgadmin.browser',
@@ -122,7 +127,23 @@ define('pgadmin.node.mview', [
           icon: 'fa fa-sync-alt',
         }]);
       },
-
+      getSchema: function(treeNodeInfo, itemNodeData) {
+        return new MViewSchema(
+          (privileges)=>getNodePrivilegeRoleSchema('', treeNodeInfo, itemNodeData, privileges),
+          ()=>getNodeVacuumSettingsSchema(this, treeNodeInfo, itemNodeData),
+          {
+            role: ()=>getNodeListByName('role', treeNodeInfo, itemNodeData),
+            schema: ()=>getNodeListByName('schema', treeNodeInfo, itemNodeData, {cacheLevel: 'database'}),
+            spcname: ()=>getNodeListByName('tablespace', treeNodeInfo, itemNodeData, {}, (m)=> {
+              return (m.label != 'pg_global');
+            }),
+          },
+          {
+            owner: pgBrowser.serverInfo[treeNodeInfo.server._id].user.name,
+            schema: treeNodeInfo.schema.label
+          }
+        );
+      },
       /**
         Define model for the view node and specify the
         properties of the model in schema.
@@ -142,9 +163,6 @@ define('pgadmin.node.mview', [
         },
         defaults: {
           spcname: undefined,
-          toast_autovacuum_enabled: 'x',
-          autovacuum_enabled: 'x',
-          warn_text: undefined,
         },
         schema: [{
           id: 'name', label: gettext('Name'), cell: 'string',
@@ -156,81 +174,9 @@ define('pgadmin.node.mview', [
           id: 'owner', label: gettext('Owner'), cell: 'string',
           control: 'node-list-by-name', select2: { allowClear: false },
           node: 'role', disabled: 'inSchema',
-        },{
-          id: 'schema', label: gettext('Schema'), cell: 'string', first_empty: false,
-          control: 'node-list-by-name', type: 'text', cache_level: 'database',
-          node: 'schema', mode: ['create', 'edit'], cache_node: 'database',
-          disabled: 'inSchema', select2: { allowClear: false },
-        },{
-          id: 'system_view', label: gettext('System materialized view?'), cell: 'string',
-          type: 'switch', mode: ['properties'],
-        }, pgBrowser.SecurityGroupSchema, {
-          id: 'acl', label: gettext('Privileges'),
-          mode: ['properties'], type: 'text', group: gettext('Security'),
         },{
           id: 'comment', label: gettext('Comment'), cell: 'string',
           type: 'multiline',
-        },{
-          id: 'definition', label: gettext('Definition'), cell: 'string',
-          type: 'text', mode: ['create', 'edit'], group: gettext('Definition'),
-          tabPanelCodeClass: 'sql-code-control',
-          control: Backform.SqlCodeControl.extend({
-            onChange: function() {
-              Backform.SqlCodeControl.prototype.onChange.apply(this, arguments);
-              if(this.model && this.model.changed) {
-                if(this.model.origSessAttrs && (this.model.changed.definition != this.model.origSessAttrs.definition)) {
-                  this.model.warn_text = gettext(
-                    'Updating the definition will drop and re-create the materialized view. It may result in loss of information about its dependent objects.'
-                  ) + '<br><br><b>' + gettext('Do you want to continue?') +
-                    '</b>';
-                }
-                else {
-                  this.model.warn_text = undefined;
-                }
-              }
-              else {
-                this.model.warn_text = undefined;
-              }
-            },
-          }),
-        },{
-          id: 'with_data', label: gettext('With data?'),
-          group: gettext('Storage'), mode: ['edit', 'create'],
-          type: 'switch',
-        },{
-          id: 'spcname', label: gettext('Tablespace'), cell: 'string',
-          type: 'text', group: gettext('Storage'), first_empty: false,
-          control: 'node-list-by-name', node: 'tablespace', select2: { allowClear: false },
-          filter: function(m) {
-            return (m.label != 'pg_global');
-          },
-        },{
-          id: 'fillfactor', label: gettext('Fill factor'),
-          group: gettext('Storage'), mode: ['edit', 'create'],
-          type: 'int', min: 10, max: 100,
-        },{
-          id: 'vacuum_settings_str', label: gettext('Storage settings'),
-          type: 'multiline', group: gettext('Storage'), mode: ['properties'],
-        },{
-          type: 'nested', control: 'tab', id: 'materialization',
-          label: gettext('Parameter'), mode: ['edit', 'create'],
-          group: gettext('Parameter'),
-          schema: Backform.VacuumSettingsSchema,
-        },{
-          // Add Privilege Control
-          id: 'datacl', label: gettext('Privileges'), type: 'collection',
-          model: pgBrowser.Node.PrivilegeRoleModel.extend({
-            privileges: ['a', 'r', 'w', 'd', 'D', 'x', 't'],
-          }), uniqueCol : ['grantee'], editable: false,
-          group: 'security', canAdd: true, canDelete: true,
-          mode: ['edit', 'create'], control: 'unique-col-collection',
-        },{
-        // Add Security Labels Control
-          id: 'seclabels', label: gettext('Security labels'),
-          model: pgBrowser.SecLabelModel, editable: false, type: 'collection',
-          canEdit: false, group: 'security', canDelete: true,
-          mode: ['edit', 'create'], canAdd: true,
-          control: 'unique-col-collection', uniqueCol : ['provider'],
         }],
         sessChanged: function() {
           /* If only custom autovacuum option is enabled the check if the options table is also changed. */
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.ui.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.ui.js
new file mode 100644
index 000000000..f7a52d7ac
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.ui.js
@@ -0,0 +1,179 @@
+/////////////////////////////////////////////////////////////
+//
+// 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 BaseUISchema from 'sources/SchemaView/base_schema.ui';
+import SecLabelSchema from '../../../../../static/js/sec_label.ui';
+import { isEmptyString } from 'sources/validators';
+
+
+export default class MViewSchema extends BaseUISchema {
+  constructor(getPrivilegeRoleSchema, getVacuumSettingsSchema, fieldOptions={}, initValues) {
+    super({
+      spcname: undefined,
+      toast_autovacuum_enabled: 'x',
+      autovacuum_enabled: 'x',
+      warn_text: undefined,
+      ...initValues
+    });
+    this.getPrivilegeRoleSchema = getPrivilegeRoleSchema;
+    this.getVacuumSettingsSchema = getVacuumSettingsSchema;
+    this.fieldOptions = {
+      role: [],
+      schema: [],
+      spcname: [],
+      nodeInfo: null,
+      ...fieldOptions,
+    };
+
+    this.nodeInfo = this.fieldOptions.nodeInfo;
+  }
+
+  get idAttribute() {
+    return 'oid';
+  }
+
+  inSchema() {
+    if(this.nodeInfo && 'catalog' in this.nodeInfo)
+    {
+      return true;
+    }
+    return false;
+  }
+
+
+  get baseFields() {
+    let obj = this;
+    return [
+      {
+        id: 'name', label: gettext('Name'), cell: 'text',
+        type: 'text', disabled: obj.inSchema, noEmpty: true,
+      },{
+        id: 'oid', label: gettext('OID'), cell: 'text',
+        type: 'text', mode: ['properties'],
+      },{
+        id: 'owner', label: gettext('Owner'),
+        type: 'select', cell: 'text',
+        options: obj.fieldOptions.role, controlProps: { allowClear: false },
+        disabled: obj.inSchema,
+      },{
+        id: 'schema', label: gettext('Schema'), cell: 'text',
+        type: 'select', options: obj.fieldOptions.schema, mode: ['create', 'edit'],
+        cache_node: 'database', disabled: obj.inSchema,
+        controlProps: {
+          allowClear: false,
+          first_empty: false
+        },
+      },{
+        id: 'system_view', label: gettext('System materialized view?'), cell: 'text',
+        type: 'switch', mode: ['properties'],
+      },
+      {
+        id: 'acl', label: gettext('Privileges'),
+        mode: ['properties'], type: 'text', group: gettext('Security'),
+      },{
+        id: 'comment', label: gettext('Comment'), cell: 'text',
+        type: 'multiline',
+      },{
+        id: 'definition', label: gettext('Definition'), cell: 'text',
+        type: 'sql', mode: ['create', 'edit'], group: gettext('Definition'),
+        isFullTab: true, controlProps: { readOnly: this.nodeInfo && 'catalog' in this.nodeInfo ? true: false },
+      },{
+        id: 'with_data', label: gettext('With data?'),
+        group: gettext('Storage'), mode: ['edit', 'create'],
+        type: 'switch',
+      },{
+        id: 'spcname', label: gettext('Tablespace'), cell: 'text',
+        type: 'select', group: gettext('Storage'),
+        options: obj.fieldOptions.spcname,
+        controlProps: {
+          allowClear: false,
+          first_empty: false,
+        },
+      },{
+        id: 'fillfactor', label: gettext('Fill factor'),
+        group: gettext('Storage'), mode: ['edit', 'create'],
+        noEmpty: false, type: 'int', controlProps: {min: 10, max: 100}
+      },{
+        id: 'vacuum_settings_str', label: gettext('Storage settings'),
+        type: 'multiline', group: gettext('Storage'), mode: ['properties'],
+      },
+      {
+        type: 'nested-tab', group: gettext('Parameter'), mode: ['create', 'edit'],
+        schema: this.getVacuumSettingsSchema(),
+      },
+      /*{
+        type: 'nested', control: 'tab', id: 'materialization',
+        label: gettext('Parameter'), mode: ['edit', 'create'],
+        group: gettext('Parameter'),
+        schema: Backform.VacuumSettingsSchema,
+      },
+      {
+        // Add Privilege Control
+        id: 'datacl', label: gettext('Privileges'), type: 'collection',
+        model: pgBrowser.Node.PrivilegeRoleModel.extend({
+          privileges: ['a', 'r', 'w', 'd', 'D', 'x', 't'],
+        }), uniqueCol : ['grantee'], editable: false,
+        group: 'security', canAdd: true, canDelete: true,
+        mode: ['edit', 'create'], control: 'unique-col-collection',
+      },*/
+      {
+        id: 'datacl', label: gettext('Privileges'), type: 'collection',
+        schema: this.getPrivilegeRoleSchema(['U']),
+        uniqueCol : ['grantee'],
+        editable: false,
+        group: gettext('Security'), mode: ['edit', 'create'],
+        canAdd: true, canDelete: true,
+      },
+      {
+      // Add Security Labels Control
+        id: 'seclabels', label: gettext('Security labels'),
+        schema: new SecLabelSchema(),
+        editable: false, type: 'collection',
+        canEdit: false, group: gettext('Security'), canDelete: true,
+        mode: ['edit', 'create'], canAdd: true,
+        control: 'unique-col-collection',
+        uniqueCol : ['provider'],
+      }
+    ];
+  }
+
+  validate(state, setError) {
+    let errmsg = null;
+    let obj = this;
+
+    if (isEmptyString(state.service)) {
+
+      /* mview definition validation*/
+      if (isEmptyString(state.definition)) {
+        errmsg = gettext('Please enter view definition.');
+        setError('definition', errmsg);
+        return true;
+      } else {
+        errmsg = null;
+        setError('definition', errmsg);
+      }
+
+      if (state.definition) {
+        obj.warningText = null;
+        if (obj.origData.oid !== undefined && state.definition !== obj.origData.definition) {
+          obj.warningText = gettext(
+            'Updating the definition will drop and re-create the materialized view. It may result in loss of information about its dependent objects.'
+          ) + '<br><br><b>' + gettext('Do you want to continue?') + '</b>';
+        }
+      }
+      return false;
+    } else {
+      errmsg = null;
+      _.each(['definition'], (item) => {
+        setError(item, errmsg);
+      });
+    }
+  }
+}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/view.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/view.js
index 2f196ef63..4b38ff7fe 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/view.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/view.js
@@ -104,7 +104,7 @@ define('pgadmin.node.view', [
           },
           {
             owner: pgBrowser.serverInfo[treeNodeInfo.server._id].user.name,
-            schema: treeNodeInfo.schema.label
+            schema: treeNodeInfo.schema ? treeNodeInfo.schema.label : ''
           }
         );
       },
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/view.ui.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/view.ui.js
index 136d68d0d..89cdf8c23 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/view.ui.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/view.ui.js
@@ -36,7 +36,7 @@ export default class ViewSchema extends BaseUISchema {
   }
 
   notInSchema() {
-    if(this.node_info && 'catalog' in this.node_info) {
+    if(this.nodeInfo && 'catalog' in this.nodeInfo) {
       return true;
     }
     return false;
@@ -96,7 +96,7 @@ export default class ViewSchema extends BaseUISchema {
       id: 'definition', label: gettext('Code'), cell: 'text',
       type: 'sql', mode: ['create', 'edit'], group: gettext('Code'),
       isFullTab: true,
-      disabled: obj.notInSchema,
+      controlProps: { readOnly: obj.nodeInfo && 'catalog' in obj.nodeInfo ? true: false },
     },
 
     {
@@ -142,7 +142,7 @@ export default class ViewSchema extends BaseUISchema {
           state.definition !== obj.origData.definition
         )) {
           obj.warningText = null;
-          return true;
+          return false;
         }
 
         let old_def = obj.origData.definition &&
@@ -169,7 +169,7 @@ export default class ViewSchema extends BaseUISchema {
         } else {
           obj.warningText = null;
         }
-        return true;
+        return false;
       }
 
     } else {
diff --git a/web/regression/javascript/schema_ui_files/mview.ui.spec.js b/web/regression/javascript/schema_ui_files/mview.ui.spec.js
new file mode 100644
index 000000000..66a9b48c0
--- /dev/null
+++ b/web/regression/javascript/schema_ui_files/mview.ui.spec.js
@@ -0,0 +1,135 @@
+/////////////////////////////////////////////////////////////
+//
+// 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 MViewSchema from '../../../pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.ui';
+
+
+class MockSchema extends BaseUISchema {
+  get baseFields() {
+    return [];
+  }
+}
+
+describe('MaterializedViewSchema', ()=>{
+  let mount;
+  let schemaObj = new MViewSchema(
+    ()=>new MockSchema(),
+    ()=>new MockSchema(),
+    {
+      role: ()=>[],
+      schema: ()=>[],
+      spcname: ()=>[],
+    },
+    {
+      owner: 'postgres',
+      schema: '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.definition = null;
+    schemaObj.validate(state, setError);
+    expect(setError).toHaveBeenCalledWith('definition', 'Please enter view definition.');
+
+    state.definition = 'SELECT 1;';
+    schemaObj.validate(state, setError);
+    expect(setError).toHaveBeenCalledWith('definition', null);
+
+    state.definition = 'SELECT 1';
+    schemaObj.validate(state, setError);
+    expect(setError).toHaveBeenCalledWith('definition', null);
+
+    state.service = 'Test';
+    state.definition = 'SELECT 1';
+    schemaObj.validate(state, setError);
+    expect(setError).toHaveBeenCalledWith('definition', null);
+
+  });
+});
+
diff --git a/web/regression/javascript/schema_ui_files/view.ui.spec.js b/web/regression/javascript/schema_ui_files/view.ui.spec.js
index d801b1c0b..244a55390 100644
--- a/web/regression/javascript/schema_ui_files/view.ui.spec.js
+++ b/web/regression/javascript/schema_ui_files/view.ui.spec.js
@@ -15,7 +15,7 @@ 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 ViewSchema from '../../../pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/view.ui.js';
+import ViewSchema from '../../../pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/view.ui';
 
 
 class MockSchema extends BaseUISchema {
