<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Inandu SAS</title>
    <description>The latest articles on DEV Community by Inandu SAS (@inandusolutions).</description>
    <link>https://dev.to/inandusolutions</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4104479%2Ffdf2b194-c43e-4296-9630-473321405c33.png</url>
      <title>DEV Community: Inandu SAS</title>
      <link>https://dev.to/inandusolutions</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/inandusolutions"/>
    <language>en</language>
    <item>
      <title>Why we built an MIT Angular data grid instead of paying for the enterprise tier</title>
      <dc:creator>Inandu SAS</dc:creator>
      <pubDate>Tue, 01 Sep 2026 13:51:49 +0000</pubDate>
      <link>https://dev.to/inandusolutions/why-we-built-an-mit-angular-data-grid-instead-of-paying-for-the-enterprise-tier-4d9k</link>
      <guid>https://dev.to/inandusolutions/why-we-built-an-mit-angular-data-grid-instead-of-paying-for-the-enterprise-tier-4d9k</guid>
      <description>&lt;p&gt;Every Angular app of a certain size eventually needs a &lt;em&gt;real&lt;/em&gt; data grid. Not a&lt;br&gt;
styled &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt; — a grid: sortable and filterable columns, row grouping,&lt;br&gt;
aggregation, an Excel export, sticky columns, inline editing, virtual scroll for&lt;br&gt;
the big lists.&lt;/p&gt;

&lt;p&gt;When you go shopping for one, the market sorts itself into two piles pretty&lt;br&gt;
quickly:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Lightweight grids&lt;/strong&gt; that do sorting, filtering and paging, and stop there.
The moment you need grouping or an export, you're writing it yourself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full-featured grids&lt;/strong&gt; where the genuinely useful parts — row grouping,
Excel export, cell-range selection, aggregation, tree data, pivoting — live
behind a per-developer &lt;strong&gt;enterprise licence&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We kept landing in pile 2, and kept bouncing off the same wall. This is why we&lt;br&gt;
ended up building &lt;a href="https://github.com/inandusolutions/inandu-grid" rel="noopener noreferrer"&gt;&lt;strong&gt;inandu-grid&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
— &lt;code&gt;@inandu-solutions/grid-angular&lt;/code&gt;, MIT, every feature free — and the decisions&lt;br&gt;
that shaped it.&lt;/p&gt;
&lt;h2&gt;
  
  
  The enterprise-tier tax
&lt;/h2&gt;

&lt;p&gt;The commercial Angular grids are good software. That's not the complaint. The&lt;br&gt;
complaint is &lt;em&gt;which&lt;/em&gt; features are gated.&lt;/p&gt;

&lt;p&gt;Look at what a typical "Enterprise" tier includes: row grouping, aggregation,&lt;br&gt;
the Excel exporter, cell-range selection, master/detail, tree data, pivoting,&lt;br&gt;
the server-side row model. Now look at your requirements doc. For a lot of&lt;br&gt;
line-of-business apps, that list &lt;em&gt;is&lt;/em&gt; the requirements doc. The free core gets&lt;br&gt;
you a sortable table; the paid tier gets you the thing you were actually asked&lt;br&gt;
to build.&lt;/p&gt;

&lt;p&gt;And the licence itself has a cost beyond the invoice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It's per-seat.&lt;/strong&gt; Every developer who touches the repo needs a seat, CI
sometimes counts, and you get to have a conversation with procurement and
legal before you can &lt;code&gt;npm install&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's a redistribution question.&lt;/strong&gt; If you ship a product that embeds the
grid, or you're an agency building for clients, the licensing math gets its
own meeting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It follows you to renewal.&lt;/strong&gt; The dependency doesn't stop being load-bearing
when the term ends.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a large app with a budget and a need for pivoting and integrated charts,&lt;br&gt;
that's a completely reasonable trade — and if that's you, &lt;strong&gt;AG Grid Enterprise&lt;br&gt;
is genuinely the right tool&lt;/strong&gt; and you should buy it. But a huge number of teams&lt;br&gt;
are paying that tax for &lt;em&gt;grouping and an Excel button&lt;/em&gt;, and that felt like a gap&lt;br&gt;
worth filling.&lt;/p&gt;
&lt;h2&gt;
  
  
  What we wanted instead
&lt;/h2&gt;

&lt;p&gt;The brief we wrote for ourselves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MIT, in full.&lt;/strong&gt; No tier. Row grouping, aggregates, CSV/Excel/PDF export,
cell-range selection, inline editing — all in the one package, all under the
one licence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Small dependency footprint.&lt;/strong&gt; A grid shouldn't dominate your bundle. It has
four runtime dependencies: &lt;code&gt;@angular/cdk&lt;/code&gt; (virtual scroll),
&lt;code&gt;@ngx-translate/core&lt;/code&gt; (i18n), &lt;code&gt;jspdf&lt;/code&gt; (PDF export) and &lt;code&gt;tslib&lt;/code&gt; (the TypeScript
helper runtime). &lt;code&gt;jspdf&lt;/code&gt; is lazy-loaded, so you only pay for it if you call
the PDF exporter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Angular-native, current-Angular.&lt;/strong&gt; Standalone components, signal-based
inputs and outputs, no &lt;code&gt;NgModule&lt;/code&gt;s, no &lt;code&gt;zone.js&lt;/code&gt; assumptions baked into the
public API. Two components you import and use:
&lt;code&gt;&amp;lt;inandu-grid&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;inandu-column&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The grid never owns your data.&lt;/strong&gt; It consumes a plain array and &lt;em&gt;emits&lt;/em&gt;
every mutation — &lt;code&gt;rowSave&lt;/code&gt;, &lt;code&gt;rowCreate&lt;/code&gt;, &lt;code&gt;rowDelete&lt;/code&gt;, &lt;code&gt;selectionChange&lt;/code&gt;. It
never reaches into your model. Fetching, persistence and optimistic updates
stay in your app, where they belong.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Honest scope.&lt;/strong&gt; No pivoting. No integrated charts. No built-in server-side
row model (there's a &lt;code&gt;serverSide&lt;/code&gt; mode that turns off local sort/filter/page
and emits the events for you to fetch each page — but you write the fetch).
If those are hard requirements, we'll tell you to go buy the enterprise grid.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last point matters. "Lightweight alternative to the big commercial grids"&lt;br&gt;
only means something if you're willing to say what you left out.&lt;/p&gt;
&lt;h2&gt;
  
  
  What it looks like in code
&lt;/h2&gt;

&lt;p&gt;Both components are standalone, so they go straight into a component's&lt;br&gt;
&lt;code&gt;imports&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;InanduGridComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;InanduColumnComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;InanduGridRow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@inandu-solutions/grid-angular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-people&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;InanduGridComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;InanduColumnComponent&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;inandu-grid
      [data]="rows"
      [paging]="{ pageSize: 10 }"
      filter="true"
      lang="en"&amp;gt;
      &amp;lt;inandu-column field="name"   title="Name"   sortable="true"&amp;gt;&amp;lt;/inandu-column&amp;gt;
      &amp;lt;inandu-column field="age"    title="Age"    type="number"  sortable="true" aggregate="avg"&amp;gt;&amp;lt;/inandu-column&amp;gt;
      &amp;lt;inandu-column field="team"   title="Team"   groupable="true"&amp;gt;&amp;lt;/inandu-column&amp;gt;
      &amp;lt;inandu-column field="joined" title="Joined" type="date"    format="DD/MM/YYYY"&amp;gt;&amp;lt;/inandu-column&amp;gt;
      &amp;lt;inandu-column field="active" title="Active" type="boolean" format="Yes|No"&amp;gt;&amp;lt;/inandu-column&amp;gt;
    &amp;lt;/inandu-grid&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PeopleComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;InanduGridRow&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ada Lovelace&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;team&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Analytical&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;joined&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2021&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="na"&gt;active&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alan Turing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;team&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bletchley&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;joined&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2019&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  &lt;span class="na"&gt;active&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Grace Hopper&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;team&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bletchley&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;joined&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2020&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="na"&gt;active&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's grouping-by-drag, average aggregation, type-aware filtering, date&lt;br&gt;
formatting and pagination — no &lt;code&gt;NgModule&lt;/code&gt;, no config object, no licence key.&lt;br&gt;
Each feature is opt-in per column or per grid; an unconfigured grid is just a&lt;br&gt;
table.&lt;/p&gt;

&lt;p&gt;Inline editing follows the same "we don't touch your array" rule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;inandu-grid&lt;/span&gt; &lt;span class="na"&gt;[data]=&lt;/span&gt;&lt;span class="s"&gt;"rows"&lt;/span&gt; &lt;span class="na"&gt;creatable&lt;/span&gt; &lt;span class="na"&gt;deletable&lt;/span&gt; &lt;span class="na"&gt;(rowSave)=&lt;/span&gt;&lt;span class="s"&gt;"save($event)"&lt;/span&gt; &lt;span class="na"&gt;(rowCreate)=&lt;/span&gt;&lt;span class="s"&gt;"create($event)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;inandu-column&lt;/span&gt; &lt;span class="na"&gt;field=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;  &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"Name"&lt;/span&gt;  &lt;span class="na"&gt;editable=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/inandu-column&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;inandu-column&lt;/span&gt; &lt;span class="na"&gt;field=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"Email"&lt;/span&gt; &lt;span class="na"&gt;editable=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;pattern=&lt;/span&gt;&lt;span class="s"&gt;"^\S+@\S+$"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/inandu-column&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/inandu-grid&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;InanduGridRowSave&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// you decide: patch locally, call the API, roll back on failure&lt;/span&gt;
  &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The comparison, with the caveats attached
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;inandu-grid&lt;/th&gt;
&lt;th&gt;AG Grid&lt;/th&gt;
&lt;th&gt;PrimeNG Table&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Licence&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;MIT, all features&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;MIT core + &lt;strong&gt;paid Enterprise&lt;/strong&gt; (grouping, Excel, range selection, pivot, tree data…)&lt;/td&gt;
&lt;td&gt;MIT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Footprint&lt;/td&gt;
&lt;td&gt;4 runtime deps (&lt;code&gt;@angular/cdk&lt;/code&gt;, &lt;code&gt;@ngx-translate/core&lt;/code&gt;, &lt;code&gt;jspdf&lt;/code&gt; lazy-loaded, &lt;code&gt;tslib&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;large&lt;/td&gt;
&lt;td&gt;ships as part of the full PrimeNG library&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frameworks&lt;/td&gt;
&lt;td&gt;Angular only (signals, standalone)&lt;/td&gt;
&lt;td&gt;Angular / React / Vue / vanilla&lt;/td&gt;
&lt;td&gt;Angular only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Row grouping &amp;amp; aggregates&lt;/td&gt;
&lt;td&gt;✅ free&lt;/td&gt;
&lt;td&gt;Enterprise&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Excel / CSV / PDF export&lt;/td&gt;
&lt;td&gt;✅ free (&lt;code&gt;.xls&lt;/code&gt; + CSV + PDF)&lt;/td&gt;
&lt;td&gt;CSV free; Excel is Enterprise&lt;/td&gt;
&lt;td&gt;CSV free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pivoting, integrated charts&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Enterprise&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Server-side row model&lt;/td&gt;
&lt;td&gt;bring-your-own (&lt;code&gt;serverSide&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Enterprise&lt;/td&gt;
&lt;td&gt;bring-your-own&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is orientation, not a scorecard — every one of these projects moves, so&lt;br&gt;
check their own docs for the current details. AG Grid runs on four frameworks&lt;br&gt;
and does things inandu-grid deliberately doesn't. PrimeNG's table is excellent&lt;br&gt;
if you're already all-in on PrimeNG. The pitch here is narrow: &lt;strong&gt;if what you&lt;br&gt;
need is a solid, free, lightweight Angular grid and the enterprise features are&lt;br&gt;
the ones you were reaching for, you shouldn't have to pay for a tier to get&lt;br&gt;
them.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A couple of design decisions worth calling out
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Export without the weight.&lt;/strong&gt; CSV is UTF-8 with a BOM so Excel opens it&lt;br&gt;
cleanly. The "Excel" export writes SpreadsheetML (&lt;code&gt;.xls&lt;/code&gt;) and has &lt;em&gt;zero&lt;/em&gt;&lt;br&gt;
dependencies — no bundled xlsx library. PDF uses &lt;code&gt;jspdf&lt;/code&gt;, loaded lazily on first&lt;br&gt;
use. (Real &lt;code&gt;.xlsx&lt;/code&gt; is the one thing we moved into a separate paid add-on,&lt;br&gt;
&lt;code&gt;grid-pro&lt;/code&gt; — the dependency-free &lt;code&gt;.xls&lt;/code&gt; covers most "email me the numbers"&lt;br&gt;
needs.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;i18n per grid instance.&lt;/strong&gt; Five languages ship in the box (en, es, fr, it, zh)&lt;br&gt;
plus &lt;code&gt;customTranslations&lt;/code&gt;, and each grid instance is isolated — a grid set to&lt;br&gt;
&lt;code&gt;lang="es-AR"&lt;/code&gt; doesn't reach into a global translation service or affect any&lt;br&gt;
other grid on the page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Theming is just CSS.&lt;/strong&gt; Three presets (&lt;code&gt;material&lt;/code&gt;, &lt;code&gt;dark&lt;/code&gt;, &lt;code&gt;minimal&lt;/code&gt;), and&lt;br&gt;
every structural element carries a stable &lt;code&gt;inandu-*&lt;/code&gt; class with no default rule&lt;br&gt;
attached, so you style from your own global stylesheet without fighting&lt;br&gt;
specificity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this is going
&lt;/h2&gt;

&lt;p&gt;The npm name &lt;code&gt;@inandu-solutions/grid-angular&lt;/code&gt; is deliberate: the framework-agnostic&lt;br&gt;
core lives in &lt;code&gt;projects/inandu-grid/src/lib/core/&lt;/code&gt;, and the bare&lt;br&gt;
&lt;code&gt;@inandu-solutions/grid&lt;/code&gt; name is reserved for a framework-neutral umbrella. A&lt;br&gt;
React port would ship as &lt;code&gt;@inandu-solutions/grid-react&lt;/code&gt; against that same core.&lt;br&gt;
No promises on timing — but the architecture is pointed that way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live demo&lt;/strong&gt; (every feature, in the browser): &lt;a href="https://inandusolutions.github.io/inandu-grid/" rel="noopener noreferrer"&gt;https://inandusolutions.github.io/inandu-grid/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Editable StackBlitz&lt;/strong&gt;: &lt;a href="https://stackblitz.com/github/inandusolutions/inandu-grid/tree/main/examples/stackblitz" rel="noopener noreferrer"&gt;https://stackblitz.com/github/inandusolutions/inandu-grid/tree/main/examples/stackblitz&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full manual + API reference&lt;/strong&gt;: &lt;a href="https://inandusolutions.github.io/inandu-grid/manual.html" rel="noopener noreferrer"&gt;https://inandusolutions.github.io/inandu-grid/manual.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repo&lt;/strong&gt; (issues &amp;amp; PRs welcome): &lt;a href="https://github.com/inandusolutions/inandu-grid" rel="noopener noreferrer"&gt;https://github.com/inandusolutions/inandu-grid&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @inandu-solutions/grid-angular
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Requires Angular &lt;code&gt;^21.2.0&lt;/code&gt;. MIT. If you build something with it, or you hit an&lt;br&gt;
edge we haven't, open an issue — that's the fastest way this gets better.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>opensource</category>
      <category>typescript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
