---
# System prepended metadata

title: Tips & Tricks

---

# Tips & Tricks

## tips and tricks

### seeing output of macros

```nimrod=
import macros

expandmacros:
  #code
```

then during compilation it will display what the expanded code looks like

### Getting notified for QML properties changing

Each QML property has an `onChange` attached to it automatically.

For example, if you a property named `name`, it will have an `onNameChanged`. It follows the pattern: `on` + Property + `Change`.

Eg:
```
property int index: 0

onIndexChanged: {
    console.log('Index changed', index)
}
```

## Async
```nimrod
import chronos

proc someFunction*(someParameter:int): Future[string] {.async.}=
  result = "Something"
  

var myResult = waitFor someFunction(1)

# If inside some async function
var myResult = await someFunction(6464435)

# to discard the result,
asyncCheck someFunction(2332)

```

`nim-chronos` API is compatible with https://nim-lang.org/docs/asyncdispatch.html so this page can be used to complement nim-chronos lack of documentation. ([Wiki](https://github.com/status-im/nim-chronos/wiki/AsyncDispatch-comparison))

## Updating data on a QAbstractListModel
While adding/removing values from a list is easy, updating the values of a list requires some extra manipulation:
```
proc updateRecord(idx: int, newValue: string) =
    self.myList[idx] = newValue;
    var topLeft = self.createIndex(idx,0,nil)
    var bottomRight = self.createIndex(idx,0,nil)
    self.dataChanged(topLeft, bottomRight, @[RoleNames.SomeRole.int, RoleNames.AnotherRole.int, RoleNames.SomeOtherRole.int])
```

If more than one record is being updated at once, change the `topLeft`'s and `bottomRight`'s `self.createIndex` first parameter to indicate the initial row number and the final row number that were affected. 

To refresh the whole table, I think you can use `0` as the first parameter for `createIndex` for both `topLeft` and `bottomRight`. 

The final attribute of `dataChanged` is a non-empty sequence of RoleNames containing the attributes that were updated

## Error Handling and Custom Errors

### Raising Custom errors

```nim
type
  CustomError* = object of Exception # CatchableError/Defect

try:
  raise newException(CustomError, "Some error message")
except CustomError as e:
  echo e.msg
```

### Raising Custom Errors with custom data (and parent Error)

```nim
type
  CustomError* = object of Exception
     customField*: string

type CustomErrorRef = ref CustomError

try:
  raise CustomErrorRef(msg: "Some error message", customField: "Some custom error data", parent: (ref ValueError)(msg: "foo bar"))
except CustomError as e:
  echo e.msg & ": " & e.customField
  echo "Original: " & e.parent.msg
```

### Implementing custom Error helpers with default values

```nim
type
  CustomError* = object of Exception
    customField*: string

type CustomErrorRef = ref CustomError

proc newCustomError*(customData: string): CustomErrorRef =
  result = CustomErrorRef(msg: "This is some custom error message", customField: customData, parent: (ref ValueError)(msg: "Value error"))
```