Search code examples
javascriptjsondjangomention

Convert JSON from Django to JavaScript Array and Loop to Populate 'users' Parameter in Mention.js


I'm probably going about this all wrong, so I need some guidance. I'm using mention.js for linking profiles in posts in an application I'm building. Getting this working with hard coded data is trivial. Just set it up as described in the docs.

Well, for my app, each user who is logged in belongs to an organization, and this organization comes from Django as JSON. I want to populate the mention.js dropdown from which to choose with these data so when a user types, their organization list comes up. I have the JSON logged to the terminal console and browser console:

[
    {
        "fields": {
            "avatar": "images/avatars/bob.png", 
            "name": "Bob Jones"
    }, 
        "model": "accounts.profile", 
        "pk": 5
    }, 
    {
        "fields": {
            "avatar": "images/avatars/sam.png", 
            "name": "Sam Smith"
    }, 
        "model": "accounts.profile", 
        "pk": 7
    }
]

So I'm getting the correct data from Django. I can parse the data relatively easily and print to the browser console:

console.log(profile_array[0].fields.name);

The next step is to get this into the mention.js users parameter. Based on @sainaen's answer, I have this in my JavaScript:

users: profile_array.map(function (profile) {
    return {
        username: profile.fields.name, // this still missing
        name: profile.fields.name,
        image: '/media/' + profile.fields.avatar
    };
})

The problem is that my profile does not have a username field. It's linked to the User model by a OneToOne relationship. So in my view, I'm actually returning two chunks of JSON: profiles (for name and avatar) and users (for username).

I realized that I can combine these JSON objects and so I did that.

But now I'm having trouble getting the username out for the users parameter in mention.js.

UPDATE

To solve this, I added a username field to my profile model. I added some code to a save override to autopopulate theusername of the profile model to be equal to user.username. Not sure if this is the best method, but it allows for @sainaen's answer to work.


Solution

  • From the source of mention.js it looks like users is expected to be array of JS objects, so no function inside array will work. Also matching is performed on username fields and name is just for displaying results. So I think you should set not only name-s and avatar-s, but also username-s.

    Idealy, if your Django model for user will contain username, it will look like this:

    $("#some-field").mention({
        // other fields
        users: profile_array.map(function (profile) {
            return {
                username: profile.fields.username,
                name: profile.fields.name,
                avatar: profile.fields.avatar
            };
        })
     });
    

    But of course, you could convert names into usernames by yourself on the JS side, with something like:

    // converts names into usernames
    // ex: 'Bob Jones' -> 'bob_jones'
    function nameToUsername(name) {
       return name.toLowerCase().replace(/\s+/g, '_');
    }
    

    And then use it in code that creates users array:

    $("#some-field").mention({
        // other fields
        users: profile_array.map(function (profile) {
            return {
                username: nameToUsername(profile.fields.name),
                name: profile.fields.name,
                avatar: profile.fields.avatar
            };
        })
     });