View

Documentation for the View object in NocoDB Scripts

The View object represents a specific view of a table in your NocoDB base. Views provide filtered, sorted, and customized perspectives of your table data.

Overview

Views in NocoDB allow you to:

  • Apply filters to show only specific records from a table
  • Define custom sorting for records
  • Show or hide specific fields

In NocoDB Scripts, View objects provide a convenient way to work with these filtered subsets of data without having to manually implement filtering logic in your script.

Properties

PropertyTypeDescription
idstringThe unique identifier of the view
namestringThe name of the view
descriptionstring | nullThe description of the view (if any)
typestringThe type of view (e.g., 'grid', 'form', 'gallery', 'kanban', 'calendar')
tableTableReference to the parent table that this view belongs to

Methods

selectRecordsAsync

Queries records from the view with optional parameters for field selection, sorting, and pagination.

Parameters:

  • options (optional): Object with the following properties:
    • fields (Array<Field | string>): Specific fields to include in the result. If not specified, all fields are included.
    • sorts (Array<{field: Field | string, direction: 'asc' | 'desc'}>): Sorting options
    • recordIds (Array<string>): Specific record IDs to retrieve
    • pageSize (number): Maximum number of records to return per page (default: 50)
    • page (number): Page number for pagination (default: 1)
    • where (string): Where filter condition which adds to existing view filters

Returns: Promise<RecordQueryResult> - A promise that resolves to a RecordQueryResult object with pagination support

Example:

// Get the Projects table and Active Projects view
const projectsTable = base.getTable('Projects');
const activeProjectsView = projectsTable.getView('Active Projects');

// Query records from the view
const queryResult = await activeProjectsView.selectRecordsAsync({
  fields: ['Project Name', 'Status', 'Deadline', 'Assigned To'],
  sorts: [
    { field: 'Deadline', direction: 'asc' }
  ],
  pageSize: 50
});

while(queryResult.hasMoreRecords) {
  await queryResult.loadMoreRecords()
}

output.text(`Found ${queryResult.records.length} active projects.`);

// Process the records
for (const record of queryResult.records) {
  const projectName = record.getCellValue('Project Name');
  const deadline = record.getCellValue('Deadline');
  const assignedTo = record.getCellValue('Assigned To');
  
  const assigneeName = assignedTo ? assignedTo.name : 'Unassigned';
  
  output.text(`- ${projectName} due on ${deadline} - Assigned to: ${assigneeName}`);
}

selectRecordAsync

Retrieves a single record from the view by its ID, applying the view's filters and permissions.

Parameters:

  • recordId (string): The ID of the record to retrieve
  • options (optional): Object with the following properties:
    • fields (Array<Field | string>): Specific fields to include in the result. Primary key and primary value fields are automatically included.

Returns: Promise<NocoDBRecord | null> - A promise that resolves to the NocoDBRecord object or null if not found, filtered out by the view, or if an AxiosError occurs

Example:

// Get a specific record through a view
const tasksTable = base.getTable('Tasks');
const myTasksView = tasksTable.getView('My Tasks');

const recordId = 'rec12345';
const task = await myTasksView.selectRecordAsync(recordId, {
  fields: ['Task Name', 'Status', 'Due Date', 'Notes']
});

if (task) {
  output.text(`Task: ${task.getCellValue('Task Name')}`);
  output.text(`Status: ${task.getCellValue('Status')}`);
  output.text(`Due Date: ${task.getCellValue('Due Date')}`);
  output.text(`Notes: ${task.getCellValue('Notes')}`);
} else {
  output.text(`Record with ID ${recordId} not found in this view.`);
  // Note: The record might exist in the table but be filtered out by the view
}

Using Views for Filtering

One of the primary benefits of views is using them for filtering data instead of implementing complex filtering logic in your scripts.

// Example: Processing overdue tasks
const tasksTable = base.getTable('Tasks');
const overdueTasksView = tasksTable.getView('Overdue Tasks');

// This view already has filters for tasks where Due Date < Today and Status != Completed
const overdueTasks = await overdueTasksView.selectRecordsAsync({
  fields: ['Task Name', 'Due Date', 'Assigned To', 'Status']
});

while(overdueTasks.hasMoreRecords) {
  await overdueTasks.loadMoreRecords()
}

// Create a notification summary
output.markdown('# Overdue Tasks Summary');
output.text(`There are ${overdueTasks.records.length} overdue tasks.`);

// Group tasks by assignee
const tasksByAssignee = {} as Record<string, {
  name: string,
  tasks: Array<{name: string, dueDate: string}>
}>;
for (const task of overdueTasks.records) {
  const assignee = task.getCellValue('Assigned To');
  const assigneeId = assignee ? assignee.id : 'unassigned';
  const assigneeName = assignee ? assignee.name : 'Unassigned';
  
  if (!tasksByAssignee[assigneeId]) {
    tasksByAssignee[assigneeId] = {
      name: assigneeName,
      tasks: []
    };
  }
  
  tasksByAssignee[assigneeId].tasks.push({
    name: task.getCellValue('Task Name'),
    dueDate: task.getCellValue('Due Date')
  });
}

// Output summary by assignee
for (const [assigneeId, assigneeData] of Object.entries(tasksByAssignee)) {
  output.markdown(`## ${assigneeData.name}`);
  for (const task of assigneeData.tasks) {
    const daysOverdue = Math.floor((new Date() - new Date(task.dueDate)) / (1000 * 60 * 60 * 24));
    output.text(`- ${task.name} (${daysOverdue} days overdue)`);
  }
}

Creating Interactive Reports Using Views

Views can be used to create interactive reports based on different data segments.

// Let the user choose a view from the Sales table
const salesTable = base.getTable('Sales');
const viewOptions = salesTable.views.map(view => view.name);

const selectedViewName = await input.selectAsync(
  'Select a sales report view to analyze:',
  viewOptions
);

const selectedView = salesTable.getView(selectedViewName);
const sales = await selectedView.selectRecordsAsync({
  fields: ['Date', 'Amount', 'Product', 'Sales Rep', 'Region']
});

while(sales.hasMoreRecords) {
  await sales.loadMoreRecords()
}

// Calculate summary statistics
let totalSales = 0;
const salesByRep = {};
const salesByProduct = {};
const salesByRegion = {};

for (const record of sales.records) {
  const amount = record.getCellValue('Amount') || 0;
  const rep = record.getCellValue('Sales Rep');
  const product = record.getCellValue('Product');
  const region = record.getCellValue('Region');
  
  totalSales += amount;
  
  // Sales by rep
  if (rep) {
    const repName = rep.name;
    if (!salesByRep[repName]) {
      salesByRep[repName] = 0;
    }
    salesByRep[repName] += amount;
  }
  
  // Sales by product
  if (product) {
    if (!salesByProduct[product]) {
      salesByProduct[product] = 0;
    }
    salesByProduct[product] += amount;
  }
  
  // Sales by region
  if (region) {
    if (!salesByRegion[region]) {
      salesByRegion[region] = 0;
    }
    salesByRegion[region] += amount;
  }
}

// Output the report
output.markdown(`# Sales Report: ${selectedViewName}`);
output.text(`Total Sales: $${totalSales.toFixed(2)}`);
output.text(`Number of Transactions: ${sales.records.length}`);
output.text(`Average Transaction: $${(totalSales / sales.records.length).toFixed(2)}`);

// Display sales by rep
output.markdown('## Sales by Representative');
const salesByRepData = Object.entries(salesByRep)
  .map(([rep, amount]) => ({ Rep: rep, Amount: amount }))
  .sort((a, b) => b.Amount - a.Amount);
output.table(salesByRepData);

// Display sales by product
output.markdown('## Sales by Product');
const salesByProductData = Object.entries(salesByProduct)
  .map(([product, amount]) => ({ Product: product, Amount: amount }))
  .sort((a, b) => b.Amount - a.Amount);
output.table(salesByProductData);

// Display sales by region
output.markdown('## Sales by Region');
const salesByRegionData = Object.entries(salesByRegion)
  .map(([region, amount]) => ({ Region: region, Amount: amount }))
  .sort((a, b) => b.Amount - a.Amount);
output.table(salesByRegionData);

Best Practices

  1. Use views for filtering - Take advantage of views to apply complex filters rather than implementing filtering logic in your script.

  2. Remember views are read-only - View objects provide query capabilities but any record creation or updates happen at the table level.

  3. Combine with Table operations - Use views for reading/filtering and table methods for writing data.

  4. Await async operations - Always use await when calling async methods to ensure proper execution flow.