What is the reason behind fullstack-angular generator utilizing Lo-Dash's merge rather than document.set?

This is the original code snippet used for updating:

exports.update = function(req, res) {
  if(req.body._id) { delete req.body._id; }
  Thing.findById(req.params.id, function (err, thing) {
    if (err) { return handleError(res, err); }
    if(!thing) { return res.send(404); }
    var updated = _.merge(thing, req.body);
    updated.save(function (err) {
      if (err) { return handleError(res, err); }
      return res.json(200, thing);
    });
  });
};

Note particularly the line of code that reads:

var updated = _.merge(thing, req.body);
. This line works well with Schema properties that are primitives but fails when dealing with a schema property that is an array.

The main issue stems from the fact that thing is a mongoose document, whereas req.body is a javascript object.

I have formulated two hypotheses to pinpoint the core problem:

  1. _.merge() mandates the first argument to be an object, leading to conflicts when passed a document.
  2. _.merge() only successfully merges objects with equivalent keys and types. Due to one being a document and the other an object, a mismatch arises.

An illustration can be seen in this example where name updates accurately but arr does not. The update operation works seamlessly on both properties when thing.set(req.body) is utilized instead of

var updated = _.merge(thing, req.body).

thing.html

<div class="container">
  <form ng-submit="update()">
    <div class="form-group">
      <label>Name</label>
      <input class="form-control" ng-model="thing.name">
    </div>
    <div class="form-group">
      <label>Arr</label>
      <input
        type="text"
        class="form-control"
        ng-repeat="el in thing.arr"
        ng-model="thing.arr[$index]">
    </div>
    <button 
      class="btn btn-default"
      type="submit">
      Update
    </button>
  </form>

  {{thing | json}}
</div>

thing.controller.js (front end)

.controller('MainCtrl', function ($scope, $http) {
  $http.get('/api/things')
    .success(function(things) {
      $scope.thing = things[0];
    });
  $scope.update = function() {
    $http.put('/api/things/' + $scope.thing._id, $scope.thing)
      .success(function(newThing) {
        console.log('updated thing: ', newThing);
      })
      .error(function() {
        console.log('unable to update thing');
      });
  };
});

thing.model.js

'use strict';

var mongoose = require('mongoose'),
    Schema = mongoose.Schema;

var ThingSchema = new Schema({
  name: String,
  arr: []
});

module.exports = mongoose.model('Thing', ThingSchema);

thing.controller.js (backend)

'use strict';

var _ = require('lodash');
var Thing = require('./thing.model');

exports.update = function(req, res) {
  if(req.body._id) { delete req.body._id; }
  Thing.findById(req.params.id, function (err, thing) {
    if (err) { return handleError(res, err); }
    if(!thing) { return res.send(404); }
    var updated = _.merge(thing, req.body);
    updated.save(function (err) {
      if (err) { return handleError(res, err); }
      return res.json(200, thing);
    });
  });
};

function handleError(res, err) {
  return res.send(500, err);
}

These questions remain:

  1. What limitations arise from using _.merge()?
  2. Why did the developers of the angular-fullstack generator opt for _.merge()? Their choice likely hinges on a specific rationale given their knowledge of its behavior.

Answer №1

Even after trying what was recommended in a previous answer, calling 'markModified' on the _.merge return value did not solve the issue at hand. The problem identified by Adam Zerner is that using _merge results in the 'updated' object containing incorrect data for array properties. I have encountered this same issue while using the angular-fullstack generator. For instance, when I remove elements from an array, this modification does not get saved in Mongoose/mongo. However, if I utilize the set function on the mongoose document (as suggested by Zerner), the problem is resolved for me. I came across a discussion thread related to this topic: Here. It proposes replacing _merge with _extend (refer to this link), which also proved effective in solving the issue for me.

Answer №2

Make sure to use the method "markModified" with the user's information. http://mongoosejs.com/docs/api.html#document_Document-markModified

var updated = _.merge(store, req.body);
updated.markModified('foo_name');
updated.save(function (err) {
  if (err) {
    return handleError(res, err);
  }
  return res.json(200, store);
});

Answer №3

After updating from Lodash 3.10.1 to the latest version 4.6.1, I finally got _.merge to work properly. I had been struggling with this issue for some time, and even switching to _.assign in generator-angular-fullstack (version 3.3.0) didn't solve the problem as it did before. The new version of Lodash, v4.6.1, seems to have resolved this issue for me. Despite seeing many npm modules still using v3.10.1 of Lodash as a dependency, so far I haven't encountered any compatibility issues.

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

Updating the scope variable in an AngularJS directive

Recently delving into Angular, I encountered an issue: I have both a list view and a details view with tags. To facilitate navigating between the two views and loading new elements from a service upon click events, I created a directive. My aim is to also ...

Loading templates dynamically within ng-repeat is a powerful feature that enhances the flexibility and

I need help loading a template dynamically while using an ng-repeat: <ul> <li ng-repeat="prop in entity" > <div ng-include src="prop.template"></div> </li> </ul> The value of prop.template is the URL of ...

Having trouble capturing screenshots with PuppeteerJS?

I've encountered an issue while working with Puppeteer to capture screenshots from a provided URL. The code I have below doesn't seem to be functioning properly. It keeps showing the error message: [0] Error: Protocol error (Emulation.setDeviceM ...

React state update not triggering a component re-render

I've been attempting to toggle the visibility of a div by clicking on another div, but I'm encountering an issue. The div becomes invisible on the first click only if it was visible initially. After that, it remains invisible and does not update. ...

Empowering Components with React Hooks

I am currently in the process of transitioning from using class components to React hooks with the Context API. However, I am encountering an error and struggling to pinpoint the exact reason for it. Here are my Codes: // contexts/sample.jsx import React ...

Ways to prevent decreasing the value below zero in ReactJS?

I have created two buttons, one for increasing and another for decreasing a counter value. However, when I click on the minus button, it should not display negative values. But in my case, when I click on the minus button (initially at zero), it shows -1, ...

Applying multiple select filters in AngularJS to refine a scope

Check out my fiddle example here: http://jsfiddle.net/mwrLc/12/ <div ng-controller="MyCtrl"> <select ng-model="searchCountries" ng-options="cc.country for cc in countriesList | orderBy:'country'"> <option value="">Country ...

bootstrap modal dialog displayed on the edge of the webpage

I am facing an issue with a modal dialog that pops up when clicking on a thumbnail. The JavaScript code I used, which was sourced online, integrates a basic Bootstrap grid layout. The problem arises when half of the popup extends beyond the edge of the pa ...

Is it possible to utilize the cv.imencode function in Opencv.js for exporting images in the webp format?

I'm looking to convert images from various extensions like png and jpg to webp format. I initially explored using OpenCV.js but was unable to locate the cv.imencode method for creating webp images. Can anyone confirm if this method is supported? If no ...

Obtain the value of a JavaScript form with a dynamically generated field name

I am struggling with a simple javascript code and for some reason, it's not working. var number = 5; var netiteration = "net"+number; // now netiteration is equal to net5 var formvalue = document.forms.myformname.netiteration.value; Why is this co ...

It is not possible to upload files larger than 4mb in ASP.NET MVC3

I am facing an issue with uploading files in ASP.NET MVC3 where I am unable to upload files larger than 4mb. I am currently using jquery.form.js for the file upload process and utilizing ajax to post the form to the server side. It works perfectly fine whe ...

When attempting to access the property 'originalname' of an undefined nodejs Mongoose object, an error is triggered

I am attempting to save images using mongoose, express, and multer. However, I keep encountering the following error when testing with Postman: TypeError: Cannot read property 'originalname' of undefined var express=require("express") var ro ...

Encountering an issue with a MEAN application using Angular 2: The error message states "Cannot read property

As a first-time application developer, I am working on creating a system to manage Client profiles. Utilizing the Angular tour of heroes for the basic structure, I integrated mongodb and express components sourced from various online platforms. However, I ...

Performing asynchronous ajax calls with jQuery

Here is some code I have that involves a list and making an ajax call for each element in the list: util.testMethod = function(list) { var map = new Map(); list.forEach(function(data) { $.ajax({ ...

Sketch a variety of numerical values in a circular formation

I was working on a number circle using the below fiddle, but I need it to always start from 0 at the top. How can I achieve this? Additionally, I would like to connect the numbers from the inner circle border to the number with a dotted line. How can I dr ...

"Encountering perpetual null returns with Mongoose's findOne method

I am facing a new issue for the first time. Every time I call the mongoose.findOne function on my model, it returns null. Here is the code snippet: var mongoose = require('mongoose'); var Schema = mongoose.Schema; var userSchema = new Schema({ ...

Unable to view text in Angular 1.5 controller

Trying to grasp the concepts of angular 1.5 has been a challenge for me, specifically in regards to displaying text on the webpage using controllers. Instead of showing the desired content, it just displays event.name. The file in question is EventDetails ...

Experiencing difficulties in constructing a project through Angular-CLI on a Windows operating system

Encountering an error while attempting to install angular-cli with the command: npm install -g angular-cli The error message received is as follows: npm ERR! Windows_NT 10.0.14393 npm ERR! argv "C:\\Program Files\\nodejs\\n ...

Utilizing AngularJS directives with the power of string formatting

Looking at this JSON structure {textTemplate:"Name:{0},Phone:{1}",controls:[{id:1,Name:"Name",type:"text"},{id:2,Name:"Phone",type:"text"}]} I'm unsure how to utilize the directive for converting strings into HTML controls This is what I&apos ...

Dynamic Rendering of Object Arrays in Table Columns using JavaScript

In the process of developing an appointment slot selection grid, I have successfully grouped all appointments by dates. However, I am facing challenges in displaying this array of Objects as a clickable grid with columns. The current output can be viewed h ...