function getData() {
  return [
    { value: 14, type: 'age', vehicle: 'model' },
    { value: 'Female', type: 'gender', model: 'model' },
    { value: 'Happy', type: 'mood', vehicle: 'model' },
    { value: 21, type: 'age', vehicle: 'model' },
    { value: 'Male', type: 'gender', vehicle: 'model' },
    { value: 'Sad', type: 'mood', vehicle: 'model' },
    { value: 'Honda', type: 'model', vehicle: 'Manufacturer' },
  ];
}
import 'ag-grid-community/styles/ag-grid.css';
import 'ag-grid-community/styles/ag-theme-alpine.css';
import 'ag-grid-enterprise';
import { AgGridVue } from 'ag-grid-vue3';
import { createApp } from 'vue';
import MoodEditor from './moodEditorVue.js';
import NumericCellEditor from './numericCellEditorVue.js';

const VueExample = {
  template: `
        <div style="height: 100%">
        <div>TEST</div>
            <ag-grid-vue
                    style="width: 100%; height: 100%;"
                    class="ag-theme-alpine"
                    id="myGrid"
                    :columnDefs="columnDefs"
                    @grid-ready="onGridReady"
                    :defaultColDef="defaultColDef"
                    :rowData="rowData"
                    :icons="icons"
                    :suppressMenuHide="true"
                    :statusBar="statusBar"
                    
                    @row-editing-started="onRowEditingStarted"
                    @row-editing-stopped="onRowEditingStopped"
                    @cell-editing-started="onCellEditingStarted"
                    @cell-editing-stopped="onCellEditingStopped"></ag-grid-vue>
        </div>
    `,
  components: {
    'ag-grid-vue': AgGridVue,
    MoodEditor,
    NumericCellEditor,
  },
  
  data: function () {
    return {
      columnDefs: [
        {
          field: 'type',
          sortable: true,
          unSortIcon: true,
          cellStyle: {color: '#319FBE'}
        },
        {
          field: 'value',
          filter: 'agSetColumnFilter',
          suppressMenu: false,
          sortable: true,
          unSortIcon: true,
          editable: true,
          cellRenderer: function (params) {
            return (
              '<span>' +
              params.value +
              '<i class="ag-icon ag-icon-small-down"></i></span>'
            );
          },
          cellEditorSelector: (params) => {
            if (params.data.type === 'age') {
              return {
                component: 'NumericCellEditor',
              };
            }
            if (params.data.type === 'gender') {
              return {
                component: 'agSelectCellEditor',
                params: {
                  values: ['Male', 'Female'],
                },
                popup: true,
              };
            }
            if (params.data.type === 'mood') {
              return {
                component: 'MoodEditor',
                popup: true,
                popupPosition: 'under',
              };
            }
            return undefined;
          },
        },
        {
          field: 'vehicle',
          filter: 'agSetColumnFilter',
          editable: true,
          sortable: true,
          unSortIcon: true,
          cellEditorSelector: (params) => {
            if (params.data.type === 'model') {
              return {
                component: 'agSelectCellEditor',
                params: {
                  values: ['Honda', 'Toyota', 'Nissan'],
                },
                popup: true,
              };
            }
            return undefined;
          },
        },
      ],
      gridApi: null,
      columnApi: null,
      defaultColDef: {
        flex: 1,
        floatingFilter: true,
      },
      rowData: null,
    };
  },
  
  created() {
    this.rowData = getData();
    this.statusBar = {
      statusPanels: [
        { statusPanel: 'agTotalAndFilteredRowCountComponent', align: 'left' },
        { statusPanel: 'agTotalRowCountComponent', align: 'center' },
        { statusPanel: 'agAggregationComponent' },
      ],
    };
  },
  
  methods: {
    onRowEditingStarted(event) {
      console.log('never called - not doing row editing');
    },
    onRowEditingStopped(event) {
      console.log('never called - not doing row editing');
    },
    onCellEditingStarted(event) {
      console.log('cellEditingStarted');
    },
    onCellEditingStopped(event) {
      console.log('cellEditingStopped');
    },
    onGridReady(params) {
      this.gridApi = params.api;
      this.gridColumnApi = params.columnApi;
    },
  },
};

createApp(VueExample).mount('#app');
import { nextTick } from 'vue';

export default {
  template: `
      <div :ref="'container'" class="mood" tabindex="0" @keydown="onKeyDown">
      <img src="https://www.ag-grid.com/example-assets/smileys/happy.png" @click="onClick(true)" :class="{ selected: happy, default: !happy }">
      <img src="https://www.ag-grid.com/example-assets/smileys/sad.png" @click="onClick(false)" :class="{ selected: !happy, default: happy }">
      </div>
    `,
  data() {
    return {
      happy: false,
      imgForMood: null,
    };
  },
  methods: {
    getValue() {
      return this.happy ? 'Happy' : 'Sad';
    },

    setHappy(happy) {
      this.happy = happy;
    },

    toggleMood() {
      this.setHappy(!this.happy);
    },

    onClick(happy) {
      this.setHappy(happy);
      this.params.stopEditing();
    },

    onKeyDown(event) {
      let key = event.key;
      if (
        key === 'ArrowLeft' || // left
        key == 'ArrowRight'
      ) {
        // right
        this.toggleMood();
        event.stopPropagation();
      }
    },
  },
  created() {
    this.setHappy(this.params.value === 'Happy');
  },
  mounted() {
    nextTick(() => {
      this.$refs.container.focus();
    });
  },
};
import { nextTick } from 'vue';

// backspace starts the editor on Windows
const KEY_BACKSPACE = 'Backspace';
const KEY_ENTER = 'Enter';
const KEY_TAB = 'Tab';

export default {
  template: `<input :ref="'input'" class="simple-input-editor" @keydown="onKeyDown($event)" v-model="value"/>`,
  data() {
    return {
      value: '',
      cancelBeforeStart: true,
    };
  },
  methods: {
    getValue() {
      return this.value;
    },

    isCancelBeforeStart() {
      return this.cancelBeforeStart;
    },

    setInitialState(params) {
      let startValue;

      if (params.eventKey === KEY_BACKSPACE) {
        // if backspace or delete pressed, we clear the cell
        startValue = '';
      } else if (params.charPress) {
        // if a letter was pressed, we start with the letter
        startValue = params.charPress;
      } else {
        // otherwise we start with the current value
        startValue = params.value;
      }

      this.value = startValue;
    },

    // will reject the number if it greater than 1,000,000
    // not very practical, but demonstrates the method.
    isCancelAfterEnd() {
      return this.value > 1000000;
    },

    onKeyDown(event) {
      if (event.key === 'Escape') {
        return;
      }
      if (this.isLeftOrRight(event) || this.isBackspace(event)) {
        event.stopPropagation();
        return;
      }

      if (
        !this.finishedEditingPressed(event) &&
        !this.isKeyPressedNumeric(event)
      ) {
        if (event.preventDefault) event.preventDefault();
      }
    },

    isCharNumeric(charStr) {
      return /\d/.test(charStr);
    },

    isKeyPressedNumeric(event) {
      const charStr = event.key;
      return this.isCharNumeric(charStr);
    },

    finishedEditingPressed(event) {
      const key = event.key;
      return key === KEY_ENTER || key === KEY_TAB;
    },

    isBackspace(event) {
      return event.key === KEY_BACKSPACE;
    },

    isLeftOrRight(event) {
      return ['ArrowLeft', 'ArrowRight'].indexOf(event.key) > -1;
    },
  },

  created() {
    this.setInitialState(this.params);

    // only start edit if key pressed is a number, not a letter
    this.cancelBeforeStart =
      this.params.charPress && '1234567890'.indexOf(this.params.charPress) < 0;
  },
  mounted() {
    nextTick(() => {
      // need to check if the input reference is still valid - if the edit was cancelled before it started there
      // wont be an editor component anymore
      if (this.$refs.input) {
        this.$refs.input.focus();
      }
    });
  },
};
span{
  color: #585858;
}

.mood {
  border-radius: 15px;
  border: 1px solid #EDF1F5;
  background: #e6e6e6;
  padding: 15px;
  text-align: center;
  display: inline-block;
  outline: none;
}

.default {
  border: 1px solid transparent !important;
  padding: 4px;
}

.selected {
  border: 1px solid lightgreen !important;
  padding: 4px;
}

.simple-input-editor {
  width: 100%;
  height: 100%;
}

/*  Custom  */
.ag-header-row, .ag-header-row-column{
background-color: #F5F7FF;
}
.ag-rich-select-list {
    width: 100%;
    min-width: 200px;
    /*height: calc(var(--ag-row-height) * 1.5) !important;*/
    height: auto !important;
}

.ag-select .ag-picker-field-wrapper {
    min-height: 42px !important;
    width: calc()
}

.ag-theme-alpine {
  /* bright green, 10% opacity */
  --ag-selected-row-background-color: rgb(0, 255, 0, 0.1);
  --ag-odd-row-background-color: #f3f3f3;
}

.ag-root-wrapper.ag-layout-normal{
  border-radius: 10px;
}

.ag-icon.ag-icon-small-down{
float: right;
vertical-align: middle;
padding-top: 4%;
}
(function (global) {
    // simplified version of Object.assign for es3
    function assign() {
        var result = {};
        for (var i = 0, len = arguments.length; i < len; i++) {
            var arg = arguments[i];
            for (var prop in arg) {
                result[prop] = arg[prop];
            }
        }
        return result;
    }

    System.config({
        transpiler: 'plugin-babel',
        defaultExtension: 'js',
        paths:
            assign(
                {
                    // paths serve as alias
                    "npm:": "https://cdn.jsdelivr.net/npm/",
                }, systemJsPaths),
        map: assign(
            {
                // babel transpiler
                'plugin-babel': 'npm:systemjs-plugin-babel@0.0.25/plugin-babel.js',
                'systemjs-babel-build': 'npm:systemjs-plugin-babel@0.0.25/systemjs-babel-browser.js',

                // css plugin
                css: boilerplatePath + "css.js",
                // css: 'npm:systemjs-plugin-css@0.1.37/css.js',

                // vuejs
                'vue': 'npm:vue@3.2.29/dist/vue.esm-browser.js',
                '@vue/reactivity': 'npm:@vue/reactivity@3.0.0/dist/reactivity.esm-browser.prod.js',

                // vue class component
                'vue-class-component': 'npm:vue-class-component@^8.0.0-beta.3/dist/vue-class-component.cjs.js',

                app: appLocation + 'app'
            },
            systemJsMap
        ), // systemJsMap comes from index.html

        packages: {
            'vue': {
                defaultExtension: 'js'
            },
            'vue-class-component': {
                defaultExtension: 'js'
            },
            'vue-property-decorator': {
                defaultExtension: 'js'
            },
            app: {
                defaultExtension: 'js'
            },
            'ag-grid-vue3': {
                main: './lib/AgGridVue.js',
                defaultExtension: 'js'
            },
            'ag-grid-community': {
                main: './dist/ag-grid-community.cjs.min.js',
                defaultExtension: 'js'
            },
            'ag-grid-enterprise': {
                main: './dist/ag-grid-enterprise.cjs.min.js',
                defaultExtension: 'js'
            },
            '@ag-grid-community/vue3': {
                main: './lib/AgGridVue.js',
                defaultExtension: 'js'
            }
        },
        meta: {
            '*.js': {
                babelOptions: {
                    stage1: true,
                    stage2: true,
                    es2015: true
                }
            },
            '*.css': { loader: 'css' }
        }
    });
})(this);
if (typeof window !== 'undefined') {
    var waitSeconds = 100;

    var head = document.getElementsByTagName('head')[0];

    var isWebkit = !!window.navigator.userAgent.match(/AppleWebKit\/([^ ;]*)/);
    var webkitLoadCheck = function(link, callback) {
        setTimeout(function() {
            for (var i = 0; i < document.styleSheets.length; i++) {
                var sheet = document.styleSheets[i];
                if (sheet.href == link.href)
                    return callback();
            }
            webkitLoadCheck(link, callback);
        }, 10);
    };

    var cssIsReloadable = function cssIsReloadable(links) {
        // Css loaded on the page initially should be skipped by the first
        // systemjs load, and marked for reload
        var reloadable = true;
        forEach(links, function(link) {
            if(!link.hasAttribute('data-systemjs-css')) {
                reloadable = false;
                link.setAttribute('data-systemjs-css', '');
            }
        });
        return reloadable;
    }

    var findExistingCSS = function findExistingCSS(url){
        // Search for existing link to reload
        var links = head.getElementsByTagName('link')
        return filter(links, function(link){ return link.href === url; });
    }

    var noop = function() {};

    var loadCSS = function(url, existingLinks) {
        const stylesUrl = url.includes("styles.css") || url.includes("style.css");
        return new Promise((outerResolve, outerReject) => {
            setTimeout(() => {
                new Promise(function(resolve, reject) {
                    var timeout = setTimeout(function() {
                        reject('Unable to load CSS');
                    }, waitSeconds * 1000);
                    var _callback = function(error) {
                        clearTimeout(timeout);
                        link.onload = link.onerror = noop;
                        setTimeout(function() {
                            if (error) {
                                reject(error);
                                outerReject(error)
                            } else {
                                resolve('');
                                outerResolve('');
                            }
                        }, 7);
                    };
                    var link = document.createElement('link');
                    link.type = 'text/css';
                    link.rel = 'stylesheet';
                    link.href = url;
                    link.setAttribute('data-systemjs-css', '');
                    if (!isWebkit) {
                        link.onload = function() {
                            _callback();
                        }
                    } else {
                        webkitLoadCheck(link, _callback);
                    }
                    link.onerror = function(event) {
                        _callback(event.error || new Error('Error loading CSS file.'));
                    };
                    if (existingLinks.length)
                        head.insertBefore(link, existingLinks[0]);
                    else
                        head.appendChild(link);
                })
                    // Remove the old link regardless of loading outcome
                    .then(function(result){
                        forEach(existingLinks, function(link){link.parentElement.removeChild(link);})
                        return result;
                    }, function(err){
                        forEach(existingLinks, function(link){link.parentElement.removeChild(link);})
                        throw err;
                    })
            }, stylesUrl ? 5 : 0)
        })
    };

    exports.fetch = function(load) {
        // dont reload styles loaded in the head
        var links = findExistingCSS(load.address);
        if(!cssIsReloadable(links))
            return '';
        return loadCSS(load.address, links);
    };
}
else {
    var builderPromise;
    function getBuilder(loader) {
        if (builderPromise)
            return builderPromise;

        return builderPromise = System['import']('./css-plugin-base.js', module.id)
            .then(function(CSSPluginBase) {
                return new CSSPluginBase(function compile(source, address) {
                    return {
                        css: source,
                        map: null,
                        moduleSource: null,
                        moduleFormat: null
                    };
                });
            });
    }

    exports.cssPlugin = true;
    exports.fetch = function(load, fetch) {
        if (!this.builder)
            return '';
        return fetch(load);
    };
    exports.translate = function(load, opts) {
        if (!this.builder)
            return '';
        var loader = this;
        return getBuilder(loader).then(function(builder) {
            return builder.translate.call(loader, load, opts);
        });
    };
    exports.instantiate = function(load, opts) {
        if (!this.builder)
            return;
        var loader = this;
        return getBuilder(loader).then(function(builder) {
            return builder.instantiate.call(loader, load, opts);
        });
    };
    exports.bundle = function(loads, compileOpts, outputOpts) {
        var loader = this;
        return getBuilder(loader).then(function(builder) {
            return builder.bundle.call(loader, loads, compileOpts, outputOpts);
        });
    };
    exports.listAssets = function(loads, opts) {
        var loader = this;
        return getBuilder(loader).then(function(builder) {
            return builder.listAssets.call(loader, loads, opts);
        });
    };
}

// Because IE8?
function filter(arrayLike, func) {
    var arr = []
    forEach(arrayLike, function(item){
        if(func(item))
            arr.push(item);
    });
    return arr;
}

// Because IE8?
function forEach(arrayLike, func){
    for (var i = 0; i < arrayLike.length; i++) {
        func(arrayLike[i])
    }
}
<!DOCTYPE html>
<html lang="en">
	<head>
		<title>Vue 3 example</title>
		<meta charSet="UTF-8"/>
		<meta name="viewport" content="width=device-width, initial-scale=1"/>
		<style media="only screen">
            html, body{
                background-color: #F3F5F8
            }
            html, body, #app {
                height: 100%;
                width: 100%;
                margin: 0;
                box-sizing: border-box;
                -webkit-overflow-scrolling: touch;
            }

            html {
                position: absolute;
                top: 0;
                left: 0;
                padding: 0;
                overflow: auto;
            }

            body {
                padding: 1rem;
                overflow: auto;
            }
        </style>
		<link rel="stylesheet" href="styles.css"/>
	</head>
	<body>
		<div id="app">
			<my-component>Loading Vue 3 example&hellip;</my-component>
		</div>
		<script src="data.js">
		</script>
		<script>
            var appLocation = './';
            var boilerplatePath = '';
            var systemJsMap = {
                "@ag-grid-community/styles": "https://cdn.jsdelivr.net/npm/@ag-grid-community/styles@29.1.0",
                "@ag-grid-community/vue3": "https://cdn.jsdelivr.net/npm/@ag-grid-community/vue3@29.1.0/",
                "ag-grid-community": "https://cdn.jsdelivr.net/npm/ag-grid-community@29.1.0",
                "ag-grid-enterprise": "https://cdn.jsdelivr.net/npm/ag-grid-enterprise@29.1.0/",
                "ag-grid-vue3": "https://cdn.jsdelivr.net/npm/ag-grid-vue3@29.1.0/"
            };
            var systemJsPaths = {
                "@ag-grid-community/client-side-row-model": "https://cdn.jsdelivr.net/npm/@ag-grid-community/client-side-row-model@29.1.0/dist/client-side-row-model.cjs.min.js",
                "@ag-grid-community/core": "https://cdn.jsdelivr.net/npm/@ag-grid-community/core@29.1.0/dist/core.cjs.min.js",
                "@ag-grid-community/csv-export": "https://cdn.jsdelivr.net/npm/@ag-grid-community/csv-export@29.1.0/dist/csv-export.cjs.min.js",
                "@ag-grid-community/infinite-row-model": "https://cdn.jsdelivr.net/npm/@ag-grid-community/infinite-row-model@29.1.0/dist/infinite-row-model.cjs.min.js",
                "@ag-grid-enterprise/charts": "https://cdn.jsdelivr.net/npm/@ag-grid-enterprise/charts@29.1.0/dist/charts.cjs.min.js",
                "@ag-grid-enterprise/clipboard": "https://cdn.jsdelivr.net/npm/@ag-grid-enterprise/clipboard@29.1.0/dist/clipboard.cjs.min.js",
                "@ag-grid-enterprise/column-tool-panel": "https://cdn.jsdelivr.net/npm/@ag-grid-enterprise/column-tool-panel@29.1.0/dist/column-tool-panel.cjs.min.js",
                "@ag-grid-enterprise/core": "https://cdn.jsdelivr.net/npm/@ag-grid-enterprise/core@29.1.0/dist/core.cjs.min.js",
                "@ag-grid-enterprise/excel-export": "https://cdn.jsdelivr.net/npm/@ag-grid-enterprise/excel-export@29.1.0/dist/excel-export.cjs.min.js",
                "@ag-grid-enterprise/filter-tool-panel": "https://cdn.jsdelivr.net/npm/@ag-grid-enterprise/filter-tool-panel@29.1.0/dist/filter-tool-panel.cjs.min.js",
                "@ag-grid-enterprise/master-detail": "https://cdn.jsdelivr.net/npm/@ag-grid-enterprise/master-detail@29.1.0/dist/master-detail.cjs.min.js",
                "@ag-grid-enterprise/menu": "https://cdn.jsdelivr.net/npm/@ag-grid-enterprise/menu@29.1.0/dist/menu.cjs.min.js",
                "@ag-grid-enterprise/multi-filter": "https://cdn.jsdelivr.net/npm/@ag-grid-enterprise/multi-filter@29.1.0/dist/multi-filter.cjs.min.js",
                "@ag-grid-enterprise/range-selection": "https://cdn.jsdelivr.net/npm/@ag-grid-enterprise/range-selection@29.1.0/dist/range-selection.cjs.min.js",
                "@ag-grid-enterprise/rich-select": "https://cdn.jsdelivr.net/npm/@ag-grid-enterprise/rich-select@29.1.0/dist/rich-select.cjs.min.js",
                "@ag-grid-enterprise/row-grouping": "https://cdn.jsdelivr.net/npm/@ag-grid-enterprise/row-grouping@29.1.0/dist/row-grouping.cjs.min.js",
                "@ag-grid-enterprise/server-side-row-model": "https://cdn.jsdelivr.net/npm/@ag-grid-enterprise/server-side-row-model@29.1.0/dist/server-side-row-model.cjs.min.js",
                "@ag-grid-enterprise/set-filter": "https://cdn.jsdelivr.net/npm/@ag-grid-enterprise/set-filter@29.1.0/dist/set-filter.cjs.min.js",
                "@ag-grid-enterprise/side-bar": "https://cdn.jsdelivr.net/npm/@ag-grid-enterprise/side-bar@29.1.0/dist/side-bar.cjs.min.js",
                "@ag-grid-enterprise/sparklines": "https://cdn.jsdelivr.net/npm/@ag-grid-enterprise/sparklines@29.1.0/dist/sparklines.cjs.min.js",
                "@ag-grid-enterprise/status-bar": "https://cdn.jsdelivr.net/npm/@ag-grid-enterprise/status-bar@29.1.0/dist/status-bar.cjs.min.js",
                "@ag-grid-enterprise/viewport-row-model": "https://cdn.jsdelivr.net/npm/@ag-grid-enterprise/viewport-row-model@29.1.0/dist/viewport-row-model.cjs.min.js"
            };
        </script>
		<script src="https://cdn.jsdelivr.net/npm/systemjs@0.19.47/dist/system.js">
		</script>
		<script src="systemjs.config.js">
		</script>
		<script>System.import('./main.js').catch(function(err) { console.error(err); });</script>
	</body>
</html>