Michael Stum
Michael Stum

Reputation: 180964

JavaScript/jQuery DTOs/Objects to hold State

I'm usually a C# developer, but writing a mostly-client side application using jQuery.

It is reasonably straight forward: I have a list of "groups" which have some parameters (like a group name) and a list of "users" who also have some parameters.

At the moment I try to manage that using a <li> with a specific id, so there is a lot of string-matching involved to turn <li id="group-2">Name - ExtraInfo</li> back into something I can work with.

I feel that this approach is stupid because a) I use the UI as back-end for state and b) I rely on string parsing rather than working with real objects.

In C# I would just create a DTO (essentially a List<Group>), but I have not enough experience in JavaScript/jQuery to do that there.

Can someone give me some quick tips how to create a custom object and manage a list of these?

Upvotes: 3

Views: 2855

Answers (5)

JoshNaro
JoshNaro

Reputation: 2097

You can also use jQuery's data function to store groups for easy retrieval.

var group1 = {
 name: "Group 1",
 users: {
  uid1: { name: "User 1" },
  uid2: { name: "User 2" },
  uid3: { name: "User 3" }
 }
}

$('#ArbitraryElementID').data('Group 1', group1);

then you can use:

var group1 = $('#ArbitraryElementID').data('Group 1');

to retrieve the object.

Upvotes: 1

Tomalak
Tomalak

Reputation: 338248

Expanding on Ionut G. Stan's answer, I suggest nested objects:

var groups = {
  group1: {
    name: "Group 1",
    users: {
      uid1: { name: "User 1" },
      uid2: { name: "User 2" },
      uid3: { name: "User 3" }
    }
  },
  group2: {
    name: "Group 2",
    users: {
      uid1: { name: "User 1" },
      uid4: { name: "User 4" }
    }
  }
};
  • Check:
    if ("group1" in groups && "uid1" in groups["group1"].users) /* ... */;
  • Fetch:
    var username = groups["group1"].users["uid1"].name
  • Remove:
    delete groups["group1"].users["uid1"];
  • Add:
    groups["group1"].users["uid4"] = { name: "User 4" };

To avoid unnecessary duplication and insert paradoxons:

// all relevant users, for look-up purposes
var allUsers = {
  uid1: { name: "User 1" },
  uid2: { name: "User 2" },
  uid3: { name: "User 3" },
  uid4: { name: "User 4" }
}

// groups reference the ID only, details are in allUsers["uid1"] etc
var groups = {
  group1: {
    name: "Group 1",
    users: {uid1: 1, uid2: 1, uid3: 1}
  },
  group2: {
    name: "Group 2",
    users: {uid1: 1, uid4: 1 }
  }
};
  • Check:
    if ("group1" in groups && "uid1" in groups["group1"].users) /* ... */;
  • Fetch:
    var username = allUsers["uid1"].name
  • Remove:
    delete groups["group1"].users["uid1"];
  • Add:
    groups["group1"].users["uid4"] = 1;

Upvotes: 3

Jonathan Fingland
Jonathan Fingland

Reputation: 57167

You could use a structure like the following. You would want to flesh it out with more detail, and group probably has a similar structure for an internal array of users.Also some error handling for impossible values (like id = -201) wouldn't hurt.

function Group(id, name, info)
{
    var _id = id;
    var _name = name;
    var _info = info

    this.getID = function()
    {
        return _id;
    }

    this.getName = function()
    {
        return _name;
    }

    this.getInfo = function()
    {
        return _info;
    }
}

function GroupList()
{
    var _groups = [];

    this.addGroup = function(group)
    {
        _groups.push(group);
    }

    this.getGroup = function(id)
    {
        var group;
        for(var index = 0, length = _groups.length; index < length; ++index)
        {
            group = _groups[index];
            if (id === group.getID())
            {
                return group;
            }
        }
    }
}

If you're going for a OOP style as above, I'd recommend Prototype as it makes class inheritance easier. Then it's just a matter of writing a generic List and extending from that (see http://api.prototypejs.org/language/class.html). Prototype also provides, amongst other things, a pretty broad set of functions for working with arrays and enumerables (see http://api.prototypejs.org/language/enumerable.html).

Upvotes: 2

Ionuț G. Stan
Ionuț G. Stan

Reputation: 179139

I'd just use arrays and objects (let's say JSON):

var groups = [
    {
        name: "Name",
        info: "Extra"
    },
    {
        name: "Name",
        info: "Extra"
    }
];

Regarding manipulation of the array. jQuery has some array utilities. For the question in your comment, you'd use grep:

var filteredGroups = groups.grep(function (group, i) {
    return group.name == "What I'm interested in";
});

It's the equivalent of a Select().Where() in Linq (I'm not a .NET expert so there may be some things that don't match).

Anyway, that would be just the model part of an MVC structure. You still need some functions to map a collection of groups to a <ul> element. Then you'd have the view too.

Upvotes: 4

powtac
powtac

Reputation: 41050

You should not care about the string matching this is wrapped by jQuery for good reasons!

The fastest way without jQuery would be

document.getElementById('idOfLiElement');

Upvotes: 1

Related Questions