Skip to content
41 changes: 16 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,7 @@ See example [here](https://github.com/michaeljymsgutierrez/arm-js-library/tree/m
address.get('attributes.label')
```

- **Request Functions**
- **Request and Retrieve Functions**
- **save(collectionConfig)**
- Persist collection record changes to server.
- Create a new record to server only if it doesn't already exist in the database.
Expand All @@ -711,7 +711,7 @@ See example [here](https://github.com/michaeljymsgutierrez/arm-js-library/tree/m
- Will call **PUT** method: `PUT /addresses/2519858`
- Support collectionConfig. - **optional**
- Available collectionConfig `(skip, alias, autoResolve, ignorePayload, override)`
- See example [here](https://github.com/michaeljymsgutierrez/arm-js-library/tree/main/apps/create-next-app/src/app/demo/collection-records/request-functions/save)
- See example [here](https://github.com/michaeljymsgutierrez/arm-js-library/tree/main/apps/create-next-app/src/app/demo/collection-records/request-retrieve-functions/save)

```javascript
// Returned promise
Expand All @@ -727,7 +727,7 @@ See example [here](https://github.com/michaeljymsgutierrez/arm-js-library/tree/m
- Will call **GET** method: `GET /addresses/2519858`
- Support collectionConfig. - **optional**
- Available collectionConfig `(skip, alias, autoResolve, ignorePayload, override)`
- See example [here](https://github.com/michaeljymsgutierrez/arm-js-library/tree/main/apps/create-next-app/src/app/demo/collection-records/request-functions/reload)
- See example [here](https://github.com/michaeljymsgutierrez/arm-js-library/tree/main/apps/create-next-app/src/app/demo/collection-records/request-retrieve-functions/reload)

```javascript
// Returned promise
Expand All @@ -741,12 +741,20 @@ See example [here](https://github.com/michaeljymsgutierrez/arm-js-library/tree/m
})
```

- **rollbackAttributes()**
- Rollback record attributes to their original state without triggering a request.
- See example [here](https://github.com/michaeljymsgutierrez/arm-js-library/tree/main/apps/create-next-app/src/app/demo/collection-records/request-retrieve-functions/rollback-attributes)

```javascript
address.rollbackAttributes()
```

- **destroyRecord(collectionConfig)**
- Remove collection record permanently from server.
- Will call **GET** method: `DELETE /addresses/2519858`
- Support collectionConfig. - **optional**
- Available collectionConfig `(skip, alias, autoResolve, ignorePayload, override)`
- See example [here](https://github.com/michaeljymsgutierrez/arm-js-library/tree/main/apps/create-next-app/src/app/demo/collection-records/request-functions/destroy-record)
- See example [here](https://github.com/michaeljymsgutierrez/arm-js-library/tree/main/apps/create-next-app/src/app/demo/collection-records/request-retrieve-functions/destroy-record)

```javascript
// Returned promise
Expand Down Expand Up @@ -779,7 +787,7 @@ See example [here](https://github.com/michaeljymsgutierrez/arm-js-library/tree/m
- Sort returned collection records based on passed array of sort criteria.
- **config - Object**
- Contains request config such as `(skip, alias, autoResolve, ignorePayload, override)` which are currently available.
- See example [here](https://github.com/michaeljymsgutierrez/arm-js-library/tree/main/apps/create-next-app/src/app/demo/collection-records/request-functions/get-collection)
- See example [here](https://github.com/michaeljymsgutierrez/arm-js-library/tree/main/apps/create-next-app/src/app/demo/collection-records/request-retrieve-functions/get-collection)

```javascript
// Get user record from the server but don't preload addresses records.
Expand Down Expand Up @@ -1056,26 +1064,9 @@ const addresses = [

## Credits

<a href="https://www.facebook.com/skpcls" title="Axl Asuncion (Graphic Artist) - Original logo/design creator">
<img
src="https://assets-omega-neon.vercel.app/images/axl.png"
alt="Axl Asuncion"
height="40" width="40" />
</a>

<a href="https://github.com/luigircruz" title="Luigi Cruz (Developer) - Features and bugs feedback" >
<img
src="https://assets-omega-neon.vercel.app/images/luigi.png"
alt="Luigi Cruz"
height="40" width="40" />
</a>

<a href="https://github.com/DicksonPal" title="Dickson Palomeras (Developer) - Features and bugs feedback" >
<img
src="https://assets-omega-neon.vercel.app/images/dickson.png"
alt="Dickson Palomeras"
height="40" width="40" />
</a>
- **[Axl Asuncion](https://www.facebook.com/skpcls)** - Original logo/design creator
- **[Luigi Cruz](https://github.com/luigircruz)** - Features and bugs feedback
- **[Dickson Palomeras](https://github.com/DicksonPal)** - Features and bugs feedback

## License

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
'use client'

import { observer } from 'mobx-react'
import Model from './model'

const Page = observer(() => {
const { isLoading, data: address } = Model()

if (isLoading) return <div>Loading...</div>

return (
<form onSubmit={(event) => event.preventDefault()}>
<div className="form-control">
<label htmlFor="address1">Address1</label>
<input
type="text"
name="address1"
value={address.get('attributes.address1') ?? ''}
onChange={(event) =>
address.set('attributes.address1', event.target.value)
}
/>
</div>

<div className="form-control">
<label htmlFor="address2">Address2</label>
<input
type="text"
name="address2"
value={address.get('attributes.address2') ?? ''}
onChange={(event) =>
address.set('attributes.address2', event.target.value)
}
/>
</div>

<div className="form-control">
<label htmlFor="city">City</label>
<input
type="text"
name="city"
value={address.get('attributes.city') ?? ''}
onChange={(event) =>
address.set('attributes.city', event.target.value)
}
/>
</div>

<div className="form-control">
<label htmlFor="post-code">Post code</label>
<input
type="text"
name="post-code"
value={address.get('attributes.post-code') ?? ''}
onChange={(event) =>
address.set('attributes.post-code', event.target.value)
}
/>
</div>

<div className="form-control">
<label htmlFor="landmark">Landmark</label>
<input
type="text"
name="landmark"
value={address.get('attributes.landmark') ?? ''}
onChange={(event) =>
address.set('attributes.landmark', event.target.value)
}
/>
</div>

<div className="form-control">
<label htmlFor="kind">Kind</label>
<input
type="text"
name="kind"
value={address.get('attributes.kind') ?? ''}
onChange={(event) =>
address.set('attributes.kind', event.target.value)
}
/>
</div>

<div className="form-control">
<label htmlFor="label">Label</label>
<input
type="text"
name="label"
value={address.get('attributes.label') ?? ''}
onChange={(event) =>
address.set('attributes.label', event.target.value)
}
/>
</div>

<div className="form-control">
<label htmlFor="latitude">Latitude</label>
<input
type="text"
name="latitude"
value={address.get('attributes.latitude')}
onChange={(event) =>
address.set('attributes.latitude', event.target.value)
}
/>
</div>

<div className="form-control">
<label htmlFor="longitude">Longitude</label>
<input
type="text"
name="longitude"
value={address.get('attributes.longitude')}
onChange={(event) =>
address.set('attributes.longitude', event.target.value)
}
/>
</div>

<div className="form-control">
<button
className="blue-btn"
onClick={() => address.rollbackAttributes()}>
Rollback Attributes
</button>
</div>
</form>
)
})

export default Page
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { ARM } from '@/components/providers/arm-config-provider'

const Model = () => {
return ARM.findRecord('addresses', 2519858, { include: 'user' })
}

export default Model
9 changes: 5 additions & 4 deletions apps/create-next-app/src/app/demo/page.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ const highlightMatch = (text, searchTerm) => {
const DemoPage = () => {
const links = [
'/demo/collection-records/getter-setter-functions',
'/demo/collection-records/request-functions/destroy-record',
'/demo/collection-records/request-functions/get-collection',
'/demo/collection-records/request-functions/reload',
'/demo/collection-records/request-functions/save',
'/demo/collection-records/request-retrieve-functions/destroy-record',
'/demo/collection-records/request-retrieve-functions/get-collection',
'/demo/collection-records/request-retrieve-functions/reload',
'/demo/collection-records/request-retrieve-functions/rollback-attributes',
'/demo/collection-records/request-retrieve-functions/save',
'/demo/collection-records/state-properties',
'/demo/create-collection-record-function/create-record',
'/demo/push-collection-record-function/push-payload',
Expand Down
22 changes: 22 additions & 0 deletions packages/dist/arm-js-library.js
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,27 @@ Fix: Try adding ${collectionName} on your ARM config initialization.`;
}
});
}
/**
* Reverts the record's attributes to their original state.
*
* This method retrieves the stored `originalRecord` (excluding internal
* ARM properties), applies those values back to the current record instance,
* and resets the `isDirty` and `isPristine` state flags.
*
* @private
* @returns {void}
*/
_rollbackRecordAttributes() {
const originalRecord = omit(
toJS(this.originalRecord),
keysToBeOmittedOnDeepCheck
);
this.getARMContext()._setProperties(this, {
...originalRecord,
isDirty: false,
isPristine: true
});
}
/**
* Retrieves records from a specified collection based on given criteria.
*
Expand Down Expand Up @@ -695,6 +716,7 @@ Fix: Try adding ${collectionName} on your ARM config initialization.`;
get: armInstance._getRecordProperty,
set: armInstance._setRecordProperty,
setProperties: armInstance._setRecordProperties,
rollbackAttributes: armInstance._rollbackRecordAttributes,
getARMContext: () => armInstance,
save: function(collectionConfig) {
return armInstance._saveRecord(this, collectionConfig);
Expand Down
24 changes: 24 additions & 0 deletions packages/src/lib/api-resource-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,29 @@ export default class ApiResourceManager {
})
}

/**
* Reverts the record's attributes to their original state.
*
* This method retrieves the stored `originalRecord` (excluding internal
* ARM properties), applies those values back to the current record instance,
* and resets the `isDirty` and `isPristine` state flags.
*
* @private
* @returns {void}
*/
_rollbackRecordAttributes() {
const originalRecord = omit(
toJS(this.originalRecord),
keysToBeOmittedOnDeepCheck,
)

this.getARMContext()._setProperties(this, {
...originalRecord,
isDirty: false,
isPristine: true,
})
}

/**
* Retrieves records from a specified collection based on given criteria.
*
Expand Down Expand Up @@ -851,6 +874,7 @@ export default class ApiResourceManager {
get: armInstance._getRecordProperty,
set: armInstance._setRecordProperty,
setProperties: armInstance._setRecordProperties,
rollbackAttributes: armInstance._rollbackRecordAttributes,
getARMContext: () => armInstance,
save: function (collectionConfig) {
return armInstance._saveRecord(this, collectionConfig)
Expand Down
17 changes: 17 additions & 0 deletions packages/tests/units/record.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,23 @@ const execRecordTest = (ARM) => {
expect(record.get('attributes.address1')).toBe('Anabu Hills Test 4')
})

test('Verify rollbackAttributes functionality', async () => {
ARM.clearCollection('addresses')
expect(ARM.getCollection('addresses')).toHaveLength(0)

await ARM.findRecord('addresses', 2518368, null, {
autoResolve: false,
skipId: uuidv1(),
})
const record = ARM.peekRecord('addresses', 2518368)

record.set('attributes.address1', 'Anabu Hills Modified')
record.rollbackAttributes()

expect(record.get('isPristine')).toBe(true)
expect(record.get('attributes.address1')).toBe('Anabu Hills Test 4')
})

test('Verify destroyRecord functionality', async () => {
ARM.clearCollection('addresses')
expect(ARM.getCollection('addresses')).toHaveLength(0)
Expand Down
Loading