Exploring the Power of Backbone.js with Embedded One-To-Many Relationships

Creating a Survey App

Developing an application for creating surveys where each survey contains multiple questions. The questions are embedded into the survey model using embeds_many in Mongoid, resulting in a survey structure like this:

{
  "id":    "4f300a68115eed1ddf000004",
  "title": "Example Survey",
  "questions": 
  [
    {
      "id":      "4f300a68115eed1ddf00000a",
      "title":   "Share your experience with backbone.js", 
      "type":    "textarea"
    },
    {
      "title":   "Do you enjoy it?", 
      "id":      "4f300a68115eed1ddf00000b",
      "type":    "radiobutton",
      "options": ["Yes", "Yes, a lot!"]
    }
  ]
}

The survey editor includes a SurveyView to display the survey and list the questions. Clicking on a question launches a QuestionView for editing that specific question. Upon saving, the updated SurveyModel is sent to the server.

Dealing with Embedded Associations

Exploring the best approach to handle the embedded association:

One method involves passing

survey.get("questions")[any_index]
to the QuestionView. However, if the question is edited, manual search for the question.id in the model is required, which can be inefficient.

Alternatively, creating a QuestionsCollection within the SurveyModel allows for fetching a Question by id from the collection. This approach ensures automatic updates when the model is changed, although specifying a URL in the collection might result in unnecessary server requests for individual questions updates.

Seeking suggestions on how to handle this situation in accordance with the backbone framework.

Answer №1

Implementing Embedded One-to-Many Associations in Backbone.js

After taking inspiration from @Sander's answer, I decided to share my code implementation:

class Survey extends Backbone.Model
        
  # Manage the Survey.questions association for server data parsing
  parse: (resp) ->
    if @attributes?.questions?
      @attributes.questions.reset(resp.questions)
    else
      resp.questions = new QuestionsCollection(resp.questions)
    resp

  # Rebuild Survey.questions
  toJSON: ->
    attributes = _.clone(@attributes)
    attributes.questions = attributes.questions.toJSON()
    attributes

Now, I can easily perform actions like:

survey = Survey.get("my-id")
survey.questions.at(0).title = "First question"
survey.questions.at(1).title = "Second question"
survey.save()

This method proves to be quite user-friendly.

Answer №2

It is definitely possible to include a questionsCollection within your SurveyModel.

However, each question is typically viewed as an individual question with its own unique ID. Even though every question will have its own ID, it is still possible for the server to identify which survey it belongs to.

When it comes to parsing your JSON data, if you manually build your collections and models, you won't encounter this issue. But if you try to add nested JSON data, it will not automatically create a sub collection for your model. In such cases, you will need to specify these details in an overridden parse method.

Answer №3

It is possible to achieve this during the construction process.

class Survey extends Backbone.Model

initialize: ->
    @questions = new QuestionsCollection(@get('questions'))

Furthermore, you have the ability to expand the model universally in order to retrieve the nested data:

_.extend Backbone.Model::, deepToJSON: ->
  obj = @toJSON()
  _.each _.keys(obj), (key) ->
    obj[key] = obj[key].deepToJSON()  if _.isFunction(obj[key].deepToJSON)

  obj

_.extend Backbone.Collection::, deepToJSON: ->
  @map (model) ->
    model.deepToJSON()

Answer №4

One way to tackle this issue is by customizing the parse and toJSON functions. It is important to note that when the object is fetched through a collection, the context of "this" in the parse method does not refer to the model object. In this case, parse is called and the output is then passed to initialize. If you require "this" to refer to the model object for event binding purposes, an alternative option is to override the set method instead. For a demonstration of this approach, I have shared a simple script on Github.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Removing double double quotes for Javascript

My problem involves a string that represents longitude/latitude in the format of dd°mm'ss''W (note 2 single quotes after ss). To convert this string into its decimal representation, I am using the following code snippet: function dmsTodeg ...

Setting breakpoints in Node-Inspector can be quite challenging

After successfully setting up a web application, I decided it was time to learn how to properly debug it without relying on console.log. To start, I ran Node-Inspector via node-debug server.js (the main script file) and attempted to set up a breakpoint wit ...

Transforming a JSON object with Backbone and Laravel

When my Backbone application sends results to Laravel via a POST request, the data is received like this: $input = Input::json(); The returned data is in the form of a JSON object, not a string. Initially, I attempted to use json_decode to access its pro ...

Display the list items within a div only if the height is lower than a separate div

I have a scenario where I have two divs named left and right. The left div contains a list of bullets (li elements) and is floated to the left, while the right div has text and HTML content. At times, either the left or the right div may be taller than the ...

Employing useEffect within Material-UI tabs to conceal the third tab

At the page's initial load, I want to hide the first two tabs. The third tab should be visible with its content displayed right away. Currently, I can only see the content after clicking on the third tab. To troubleshoot this issue, I attempted to use ...

Comparing CakePHP's JSON and AJAX capabilities

Apologies if the title of this question is misleading. I am new to utilizing JSON and AJAX for data formatting and server updates without refreshing. As a beginner in this area, I seek clarification on the best approach. In my CakePHP web application: Is ...

The error message keeps appearing consistently. What is the best way to manage this error?

Even after entering the data in this field, it was supposed to disappear. However, that didn't happen as expected. <md-input-container class="md-block" flex-gt-sm> <label>Budget</label> <input name="budget" ng-model="newTri ...

Automatic Expansion Feature for HTML Tables

http://jsfiddle.net/bzL7p87k/ In my table, placeholders are filled with special words. However, what happens when I have more than 4 rows? For instance, if there are 21 placeholders for 21 rows? What I mean is this: I only have one row with a placeholder ...

Is there a way to customize the JSON-wrapped key for a class without being able to annotate the class with @JsonTypeInfo?

I have the following code snippet: import org.codehaus.jackson.map.*; public class MyPojo { int id; public int getId() { return this.id; } public void setId(int id) { this.id = id; } public static void main(String[] args) throws ...

It is not possible to import node_modules within an electron worker process

Question I'm currently experimenting with using web workers within an Electron application. I have been successful in creating the worker process from the renderer process, but I am encountering a crash when attempting to use require('some_modul ...

Unlocking the attributes of Angular form elements: A guide

Imagine we have a form like this <form name="myForm" data-ng-controller="Ctrl"> <input name="input" data-ng-model="userType" data-description="User Type" required> </form> When working in the controller, we can refer to the input el ...

Tips for developing a personalized form validator for validating JSON data exclusively in Angular

Within my Angular application, there exists a reactive form that has a single control known as configJson, which is visually represented by a <textarea> element in the DOM. The primary goal is to validate this specific form control to ensure that it ...

Is it better to use Opengov/mpg to analyze VIN numbers individually rather than in a looping sequence to avoid errors

I'm attempting to iterate through the feVehicle() function in the mpg package, which can be found at: https://github.com/rOpenGov/mpg I have tried providing multiple vinids to the function by looping over them and adding a 5-second delay between loo ...

The data from JSON is not being displayed on the Table View

Here is My Code: import UIKit class HomeVCHome: UIViewController, UITableViewDelegate, UITableViewDataSource { @IBOutlet weak var usernameLabel: UILabel! @IBOutlet weak var tableView: UITableView! var names: [String] = [] var contacts: [String] = [] o ...

Python: Flattening and Extracting specific JSON segments

I've got an input JSON that has the following structure: > {"payment": {"payment_id": "AA340", "payment_amt": "20", "chk_nr": "321749", "clm_list": {"dtl": [{"clm_id": "1A2345", "name": "John", adj:{"adj_id":"W123","adj_cd":"45"}}, {"clm_id": "999 ...

Guzzle version 6.x is not delivering the desired outcome as expected

My restful API returns a specific response when POSTMAN is run on the given URL: POSTMAN RUN URL DELETE https://www.example.com/api/v1/Blog/blog/13 { "status":"Failure", "message":"The specified blog post could not be found" } A ...

Combine values within a single property of an object using the reduce method

My array consists of objects structured like this: let array = [{ "Age": 20, "Name": "Kevin" }, { "Age": 15, "Name": "Alfred" }, { "Age": 30, "Name": "Joe" }]; I am aiming to transform it into an object with combined values like t ...

Adjustable height and maximum height with overflow functionality

Currently, I am in the process of developing a task manager for my application and facing an obstacle when trying to calculate the height of a widget. My goal is to determine the maximum height (assuming a minimum height is already set) by subtracting a ce ...

Is there a way to fix the issue of ContextMenu not appearing at the right position within a scrollable

I have a div within an iframe that needs to display a context menu when right-clicked. The div's length may exceed the visible area, making it scrollable. However, the issue I am facing is that the context menu appears in a different position than whe ...

How to effectively manipulate nested arrays in JavaScript without altering their references

Welcome everyone, I've been working on a project using next.js and I've encountered an issue with filtering posts. The filter function works perfectly when the posts are in a simple array like ObjChild. However, I have another section on my site ...