This is a very common side-effect of the “Reza editable grid pattern”, and you’ve already identified the root cause correctly.
The problem is not your Save button — it’s the moment you create the record.
✅ Why the “ghost” record is created
This line is the real issue:
Patch(
'Materials',
Defaults('Materials'),
{ ... }
)
When you do this on New Row, Power Apps:
-
Immediately creates a row in SharePoint
-
SharePoint assigns an ID
-
The row exists permanently
-
Your editable grid only updates it later
So if the user:
➡ that empty SharePoint row cannot be rolled back.
Power Apps has no transaction support.
That’s why validations and filtering during Save don’t help — the record already exists.
🔴 This is expected behavior (not a bug)
Reza’s demo works because:
-
users always complete the row
-
demos don’t cover abandoned rows
-
SharePoint has no draft state
In real production apps, this pattern must be slightly modified.
✅ Correct and safe architecture
❌ Do NOT create SharePoint records on “New Row”
✅ Create rows only in a local collection
Then create SharePoint records only on Save.
✅ The correct editable grid pattern
Step 1 — Load data
ClearCollect(
colGrid,
'Materials'
);
Step 2 — New row button
⚠️ No Patch here
Collect(
colGrid,
{
ID: Blank(),
CodigoMaterial: Blank(),
Descripción: Blank(),
Und: Blank(),
IsNew: true,
IsDirty: true
}
);
This row exists only in memory.
Step 3 — Track edits
On each input control:
Patch(
colGrid,
ThisItem,
{
CodigoMaterial: Self.Selected.Value,
IsDirty: true
}
);
Your dependent dropdowns will still work normally.
Step 4 — Save button logic
This is the critical part.
ForAll(
Filter(
colGrid,
!IsBlank(CodigoMaterial) &&
IsDirty = true
),
If(
IsNew,
Patch(
'Materials',
Defaults('Materials'),
{
CodigoMaterial: CodigoMaterial,
Descripción: Descripción,
Und: Und
}
),
Patch(
'Materials',
LookUp('Materials', ID = ThisRecord.ID),
{
CodigoMaterial: CodigoMaterial,
Descripción: Descripción,
Und: Und
}
)
)
);
✅ Why this works
| Problem |
Fix |
| Blank rows created |
No early Patch |
| Empty SharePoint records |
Created only on Save |
| Abandoned rows |
Never reach SharePoint |
| Validations |
Work properly |
| Dependent dropdowns |
Still function |
| Performance |
Much better |
| Data integrity |
Guaranteed |
✅ Key rule (important)
Never Patch Defaults() until the user clicks Save.
That single rule eliminates 100% of ghost rows.
✅ If you absolutely must create the ID early
(rare case — usually not needed)
Then you must clean up on Save:
RemoveIf(
'Materials',
IsBlank(CodigoMaterial)
);
…but this is risky and not recommended.
✅ Why Power Apps “creates extra rows”
It isn’t actually creating extra rows.
It’s doing exactly what you told it to do:
Patch(Defaults(List))
SharePoint has no concept of:
-
draft
-
pending
-
unsaved record
Once created, it exists.
✅ Final recommendation
✔ Use collection-first editable grid
✔ Patch SharePoint only on Save
✔ Create records only when required fields exist
✔ Never initialize SharePoint rows early
✅ Summary
Create locally → validate → then patch.
This is the production-safe version of Reza’s editable grid pattern.