Controller using the 'as' syntax fails to add new object to array

Lately, I've been experimenting with the Controller as syntax in Angular. However, I seem to be struggling to grasp its functionality. I am currently following a tutorial that utilizes $scope to bind the members of the controller function rather than using 'this' (i.e., creating var vm = this). The objective of the code is to add a newly created bookmark to an array named bookmarks within the controller. The issue arises when executing createBookmark(bookmark) and setting up Angular in index.html. Despite my efforts, I can't seem to figure out why the new bookmark is not being pushed into the bookmarks array. I even tried defining it as createBookmark(vm.bookmark), but unfortunately, this syntax is considered invalid.

Any explanations on where I might be going wrong would be extremely helpful.

MainController.js


angular
    .module('app')
    .controller('MainController', MainController);

function MainController() {
    var vm = this;

    vm.categories = [
        { 'id': 0, 'name': 'Development' },
        { 'id': 1, 'name': 'Design' },
        { 'id': 2, 'name': 'Exercise' },
        { 'id': 3, 'name': 'Humor' }
    ];

    vm.bookmarks = [
        { 'id': 0, 'title': 'AngularJS', 'url': 'http://angularjs.org', 'category': 'Development' },
        { 'id': 1, 'title': 'Egghead.io', 'url': 'http://egghead.io', 'category': 'Development' },  
    ];

    vm.currentCategory = null;

    vm.setCurrentCategory = setCurrentCategory;
    vm.isCurrentCategory = isCurrentCategory;

    vm.isCreating = false;
    vm.isEditing = false;

    vm.startCreating = startCreating;
    vm.cancelCreating = cancelCreating;
    vm.startEditing = startEditing;
    vm.cancelEditing = cancelEditing;
    vm.shouldShowCreating = shouldShowCreating;
    vm.shouldShowEditing = shouldShowEditing;

    function setCurrentCategory(category) {
        vm.currentCategory = category;
        vm.cancelCreating();
        vm.cancelEditing();
    }

    function isCurrentCategory(category) {
        return vm.currentCategory !== null && category.name === vm.currentCategory.name;
    }

    //---------------------------------------------------------------------------------------------
    // CRUD
    ---------------------------------------------------------------------------------------------

    function resetCreateForm() {
        vm.newBookmark = {
            title: "",
            url: "",
            category: vm.currentCategory
        };
    }

    function createBookmark(bookmark) {
        bookmark.id = vm.bookmarks.length;
        vm.bookmarks.push(bookmark);

        resetCreateForm();
    }

    vm.createBookmark = createBookmark;
   //---------------------------------------------------------------------------------------------
    // CREATING AND EDITING STATES
    -------------------------------------------------------------------------------------------

    function startCreating() {
        vm.isCreating = true;
        vm.isEditing = false;

        resetCreateForm();
    }

    function cancelCreating() {
        vm.isCreating = false;
    }

    function shouldShowCreating() {
        return vm.currentCategory && !vm.isEditing;
    }

index.html

<!-- Content: Bookmarks-->
        <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
            <div ng-repeat="bookmark in vm.bookmarks | filter:{category:vm.currentCategory.name}">
                <button type="button" class="close">&times;</button>
                <button type="button" ng-click="vm.startEditing()" class="btn btn-link"><span class="glyphicon glyphicon-pencil"></span>
            </button>
                <a href="{{ bookmark.url }}" target="_blank">{{ bookmark.title }}</a>
            </div>
            <hr>;

           <!-- Creating -->
            <div ng-if="vm.shouldShowCreating()">
                <button type="button" class="btn btn-link" ng-click="vm.startCreating()">
                    <span class="glyphicon glyphicon-plus"></span>
                    Create Bookmark
                </button>;

               <form class="create-form"  ng-show="vm.isCreating" role="form" ng-submit="vm.createBookmark(vm.newBookmark)" novalidate>;
                   <div class="form-group">
                       <label for="newBookmarkTitle">Bookmark Title</label>
                       <input type="text" class="form-control" id="newBookmarkTitle" ng-model="vm.newBookmark.title" placeholder="Enter title">
                   </div>;

                   <div class="form-group">
                       <label for="newBookmarkUrl">Bookmark URL</label>
                       <input type="text" class="form-control" id="newBookmarkURL" ng-model="vm.newBookmark.url" placeholder="Enter URL">
                   </div>;
                   <button type="submit" class="btn btn-info btn-lg">Create</button>;
                   <button type="button" class="btn btn-default btn-lg pull-right" ng-click="vm.cancelCreating()">Cancel</button>;
               </form>;

            </div>;
;

Answer №1

Instead of directly using the reference for vm.newBookmark in the vm.createBookmark function, it is important to clone the object first. This ensures that you are not manipulating the original object unintentionally, regardless of whether you are using controller as syntax or not.

By cloning the object before pushing it into the array, you avoid situations where the newly pushed object gets reset or duplicates get added to the array.

function createBookmark(bookmark) {
    var copiedBookmark = angular.copy(bookmark);
    copiedBookmark.id = vm.bookmarks.length;
    vm.bookmarks.push(copiedBookmark);

    resetCreateForm();
}

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

Having trouble drawing over buttons in HTML5 Canvas?

window.addEventListener("load", () => { const canvas = document.querySelector("#canvas"); const ctx = canvas.getContext("2d"); const color = document.querySelector("#color"); const strokeWeight = document.querySelector("#strokeWeight"); ...

Ways to retrieve textStatus beyond ajax boundaries

Do you know how to access the textStatus variable after an ajax call? I need to use this variable in an if condition. Can anyone provide assistance? $this->registerJs("colorArray = ['#ff4c4c','#32CD32']; $('.grooveTable') ...

Create separate arrays for the names and values when returning JSON

Suppose I have a JSON object like this: { "ID": 100, "Name": "Sharon", "Classes":{ "Mathematics": 4, "English": 85, "Chemistry": 70, "Physics": 4, "Biology" ...

Adding an overlay to a material UI table row: Step by step guide

My code is rendering a row in the following format: `<TableRow key={row.name} > <TableCell>{row.empId}</TableCell> <TableCell>{row.userId}</TableCell> <TableCell>{row.name}</TableCell> <TableCell>{r ...

Guide on invoking a node.js function from an express-rendered ejs page

My express server currently has a button that triggers a POST request to activate a function in my node.js server. Instead of using a traditional POST request, I am interested in implementing something like AJAX so that the page doesn't reload. Is th ...

ReactJS does not trigger a re-render when changes are made to CSS

I'm curious about the reason why ReactJS does not automatically reapply CSS to child components even when componentDidUpdate() is called. I conducted a small demo where adding a new box doesn't change the color of existing boxes, even though the ...

What is the best way to restrict the input year on @mui/x-date-pickers to a certain range?

Is there a way to restrict the input year range when using @mui/x-date-pickers? I want to limit it from 1000 to 2023 instead of being able to enter years like 0000 or 9999. https://i.stack.imgur.com/0p6j3.jpg I have tried adding a mask to InputProps in my ...

I must implement a pause in my automation script until I receive a response from an Angular HTTP request using Selenium with Java

I am a beginner in using Selenium. I'm currently working on creating a script that will log in to my website, navigate dropdown menus, click buttons, and then wait for the response of an Angular HTTP request before logging out. driver = new Chrom ...

Utilizing JQuery for retrieving a filename

I have a unique file upload button on my website. To provide the user with visual feedback about their chosen file, I modify the html of a div to display the file name. My jquery code is as follows: $("input[type=file]").change(function() { var filen ...

Retrieve Backbone data immediately following a successful Save operation

Is there a way to trigger a fetch right after saving data? I'm looking to immediately retrieve information after a successful post... Below is the code snippet in question: search: function (search) { searchM = new SearchM(); searchM.sa ...

Ant Design is incompatible with React JS projects and cannot be effectively utilized

import React from 'react'; import styled from "styled-components"; import {Col, Row} from "antd"; const TitleBig = styled.div` font-family: "Bebas Neue Pro"; font-size: 20px; `; const TitleSmall = styled.div` ...

Retrieving saved data from LocalStorage upon page reload

<div ng-repeat="section in filterSections"> <h4>{{ section.title }}</h4> <div class="checkbox" ng-click="loaderStart()" ng-if="section.control == 'checkbox'" ng-repeat="option in section.options"> <label ...

Adjusting height in Google Maps to fill the remaining space

Currently, I am developing a map application where I want the Google Maps DIV to occupy the remaining height under the header. Here is the code snippet: <!DOCTYPE html> <head> <title>Map Application</title> <style type ...

Ways to enhance an image by zooming in when the user reaches a designated area on the webpage

I have implemented a feature where an image zooms in to letter L when the user scrolls on the page. However, I want this zoom effect to occur only when the user reaches a specific section of the site, rather than immediately when the image loads. In my exa ...

Issue detected in rxjs-compat operator's shareReplay file at line 2, column 10:

I've encountered an issue with the angular material spinner I'm using in my project. The error message is as follows: ERROR in node_modules/rxjs-compat/operator/shareReplay.d.ts(2,10): error TS2305: Module '"D:/ControlCenter/ofservices ...

Show the loading icon once to indicate that the page is waiting for an AJAX call

I am currently setting up a table that is refreshed with new data every 4 seconds using AJAX. During the initial page load, I would like to show a loading message while waiting for the AJAX to complete. Currently, I have successfully displayed the loading ...

Can you provide examples of iterating through multiple maps with key-value pairs using ng-repeat in AngularJS?

Within my controller, the data is structured like so: "type": [ { "aMap": {"5.0": 0}, "bMap": {"10.0": 0}, "cMap": {"15.0": 0}, "dMap": {"20.0": 0}, "desc": "CG" }, { "aMap": {"5.0": 0}, ...

Different ways to manipulate the CSS display property with JavaScript

Having trouble changing the CSS display property to "none" using JavaScript. Check out my code: <div class="mydiv" onClick="clickDiv1()">hello</div> <div class="mydiv" onClick="clickDiv2()">hi</div> <div class="mydiv" onClick=" ...

Can variables be utilized with the toastController in Ionic or Angular framework?

Is it possible to present a toast message to the user with their first name that is stored in a variable? If so, how can I achieve this? I would like to create something similar to the following: this.toastCtrl.create({ message: "Welcome user.firstname ...

JavaScript: Creating a Function that Returns an Object with an Undefined `this.variable`

While using javascript, I encountered an issue with instance variables. Declaring a variable as "this.variable" works fine until my function returns an object. However, if the function returns a String or Number, there are no issues. But when it returns ...