Nunjucks: Modify object

Created on 1 Nov 2014  Â·  10Comments  Â·  Source: mozilla/nunjucks

Hello

Let's imagine we're having an object:

{% set object = {
    title: 'title',
    content: 'content'
} %}

Is there any way to modify it's properties without overriding whole object?

For example, like:

{% set object.title = 'New title' %}

or to add another key:

{% set object.test = 'New key value' %}

Currently such attempts will return error TypeError: Cannot call method 'charAt' of undefined, of course.

Now I wonder, is there any workaroud for it, or it isn't possible and won't be ever possible too?

If I do understand it right, jinja has such possibility, with do block
http://stackoverflow.com/questions/11047886/modifying-dictionary-attributes-in-jinja2

Most helpful comment

This looks simpler and sufficient for this case:

env.addFilter('setAttribute', function(dictionary, key, value) {
            dictionary[key] = value;
            return dictionary;
        });

Usage

{% set myDict = {"key1": 0, "key2": 0, "key3": 0}%}
{% set myDict = myDict|setAttribute('key2', 123) %}
{{myDict['key2']}}

... prints "123" as expected.

All 10 comments

Duplicate of #307. I don't think nunjucks will support this.

Thanks for refing. I've missed that issue.

Jinja has do block for such purposes, which probably was missed by carljm while replying and closing issue.

Considering it, maybe this issue should be closed and 307 reopened with new information?

I don't think this is really a duplicate of #307, since that was specifically about {% set %} not handling attribute updates (which it doesn't in Jinja either). The {% do %} block is a much broader feature (though object modification is one thing that it's good for). Even in Jinja, {% do %} is provided only in an optional extension. I think an implementation of {% do %} for nunjucks would be just fine, but it should probably live externally.

Hi carljm. Thanks for reply.

So, in such case this issue should be reopened as enhancement?

@ArmorDarks Well, only if an implementation of {% do %} was desired for nunjucks core. My suggestion is that it should be implemented as an external extension instead, meaning this should stay closed.

Sorry for resurrecting quite old issue. I just hope that following information might be useful for beginners, who stuck with same problem.

Solution is quite simple — to write few custom filters, they will work like a charm for modifying of arrays or objects.

Few very basic examples for arrays modifications (CoffeeScript):

# Replace last value of array with `value`
# @example {% set modifiedArray = myArray|popIn('myValue') %}
env.addFilter 'popIn', (array, value) ->
  array.pop()
  array.push(value)
  array

# Add `value` to the end of array
# @example {% set modifiedArray = myArray|pushIn('myValue') %}
env.addFilter 'pushIn', (array, value) ->
  array.push(value)
  array

With same approach you can write filters for setting objects properties too.

Unfortunately, there is no other way around until someone will implement do extension.

This looks simpler and sufficient for this case:

env.addFilter('setAttribute', function(dictionary, key, value) {
            dictionary[key] = value;
            return dictionary;
        });

Usage

{% set myDict = {"key1": 0, "key2": 0, "key3": 0}%}
{% set myDict = myDict|setAttribute('key2', 123) %}
{{myDict['key2']}}

... prints "123" as expected.

@jan-dolejsi the output is correct. You've set key2 to 123, and it prints 123 afterward. What did you expect?

This looks simpler and sufficient for this case:

env.addFilter('setAttribute', function(dictionary, key, value) {
            dictionary[key] = value;
            return dictionary;
        });

Usage

{% set myDict = {"key1": 0, "key2": 0, "key3": 0}%}
{% set myDict = myDict|setAttribute('key2', 123) %}
{{myDict['key2']}}

... prints "123" as expected.

Thank you! I had the same problem, this filter solves it!

This looks simpler and sufficient for this case:

env.addFilter('setAttribute', function(dictionary, key, value) {
            dictionary[key] = value;
            return dictionary;
        });

Usage

{% set myDict = {"key1": 0, "key2": 0, "key3": 0}%}
{% set myDict = myDict|setAttribute('key2', 123) %}
{{myDict['key2']}}

... prints "123" as expected.

Works like a charm!

Was this page helpful?
0 / 5 - 0 ratings