The challenge of Angular form data binding

I'm encountering an issue with binding an input box to a controller in Angular. Despite following tutorials, the model never updates when I access the property or check the scope using AngularJS Batarang.

Upon form submission, $scope.licenceKey remains empty!

<div ng-app="licenceApp" ng-controller="licenceController">
    <form name="licenceForm" ng-submit="applyKey()" novalidate>
        <span ng-if="!Applying">
            <input type="text" ng-model="licenceKey" ng-disabled="Applying" ng-model-options="{ debounce : { 'default' : 150 } }" username-available-validator required />
            ...

JS:

angular.module('licenceApp.controllers', [])
    .controller('licenceController', function ($scope, licenceAPIservice, $filter) {
        $scope.licenceKey = "";
        $scope.Applying = false;
        ...
        $scope.applyKey = function () {
            $scope.Applying = true;

            // $scope.licenceKey is always empty here!!
            licenceAPIservice.applyKey($scope.licenceKey).then(function (data) {
                console.log(data);

                // Update model once we have applied the key
                $scope.update();
            }, function () {
                $scope.Applying = false;
            });
        };

The username directive (although its name needs updating to reflect its function)

angular.module('licenceApp.directives', [])
    .directive('usernameAvailableValidator', function ($http, $q, licenceAPIservice) {
        return {
            require: 'ngModel',
            link: function ($scope, element, attrs, ngModel) {
                ngModel.$asyncValidators.usernameAvailable = function (username) {
                    var deferred = $q.defer();

                    licenceAPIservice.validateKey(username).then(function (data) {
                        if (data.data) {
                            deferred.resolve();
                        }
                        else {
                            deferred.reject();
                        }
                    }, function () {
                        deferred.reject();
                    });

                    return deferred.promise;
                };
            }
        }
    });

Despite entering text into the input, $scope.licenceKey always remains empty. However, the custom validation on the input functions correctly.

It's worth noting that binding to Applying for controlling view states does work!

Update

I found that by using

$scope.licenceForm.licenceKey.$modelValue
, I can retrieve the value. But why is this necessary?

Update 2

If I initially set $scope.licenceKey = "test";, it displays in the textbox on page load. However, any modifications to the textbox do not update this value.

Answer №1

It seems that the issue is arising because of your utilization of ng-if instead of ng-show directive.

The reason behind this discrepancy lies in the fact that ng-if removes the element from the DOM, whereas ng-show employs CSS rules to conceal the element.

You can explore a live example illustrating this distinction by following this link: http://jsfiddle.net/q9rnqju5/.

HTML

<div ng-app="app">
    <div ng-controller="controller">
        <div ng-show="!applying1">
            <input ng-model="value1" />
            <button ng-click="apply1()">Submit</button>
        </div>
        <div ng-if="!applying2">
            <input ng-model="value2" />
            <button ng-click="apply2()">Submit</button>
        </div>
    </div>
</div>

JS

var app = angular.module("app", []);

app.controller("controller", ["$scope", "$timeout", function($scope, $timeout) {
    $scope.apply1 = function() {
        $scope.applying1 = 1;
        $timeout(function() {
            console.log($scope.value1);
            $scope.applying1 = 0;
        }, 1000);
    };
    $scope.apply2 = function() {
        $scope.applying2 = 1;
        $timeout(function() {
            console.log($scope.value2);
            $scope.applying2 = 0;
        }, 1000);
    };
}]);

Upon submission, you will observe that the first input (implemented with ng-show) retains its value, while the second input (operating on ng-if) forfeits its value.

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

Function defined as an AngularJS component

I am facing an issue where my component is not initializing when I create it with a function that returns a component object. Can someone please help me understand the difference between these two situations? Html: <div ng-app="demoApp"> <navb ...

Adjust grading system based on user interaction with JavaScript

I am currently working on a grading system for a website and I am attempting to modify the interpretation of grades when a column is clicked. Specifically, I am looking to convert Average (%) to Letters to 4.0 Grade Average. To achieve this, I am using Jqu ...

How do you modify the SVG viewport using code?

I am looking to create a feature that allows all images inside an SVG object to be moved. My plan is to use JavaScript, and possibly jQuery, to handle mouse events (down, move, up) in order to change the viewport of the SVG. However, I am currently facing ...

Unravel the JSON structure

Here is the JSON response I received from an AJAX call: [{"id":null,"period":null,"until":null,"agent_id":"15","agent_zlecajacy_id":"15","offer_id":null,"status":"1","tytul":"Pobranie ksi\u0105g","tresc":"Pobranie ksi\u0105g","data_aktualizacji" ...

Invisibility of form data on new page - PHP and Javascript

I have a webpage with multiple hyperlinks. Each hyperlink should redirect the user to a new page with the URL sent as POST data. What I can do: 1. Open the new page successfully. The issue I'm facing: 1. On the new page, I cannot access the URL ...

Implementing a JSON array to object conversion in an Express REST API

After conducting a test on a REST API using Postman, the outcome was as follows: { "success": true, "message": "success", "data": [ { "id_buku": 9, "judul_bu ...

What are alternative ways to communicate with the backend in Backbone without relying on model.save()?

Is there a more effective method to communicate with my backend (node.js/express.js) from backbone without relying on the .save() method associated with the model? Essentially, I am looking to validate a user's input on the server side and only procee ...

What are the steps for conducting a component test with material ui?

My current component is built using . import React from 'react'; import { AppBar, Toolbar } from 'material-ui'; import { Typography } from 'material-ui'; import { MuiThemeProvider, createMuiTheme } from 'material-ui/sty ...

Angular 2 Issue: Error Message "Cannot bind to 'ngModel'" arises after FormsModule is added to app.module

I've been struggling with the data binding aspect of this tutorial for over a day now. Here's the link to the tutorial: https://angular.io/docs/ts/latest/tutorial/toh-pt1.html The error I keep encountering is: Unhandled Promise rejection: Tem ...

Building a personalized payment experience using Python Flask and Stripe Checkout

I'm attempting to set up a customized checkout integration with Stripe on my Flask web application and I've encountered some issues. After copying the code from the Stripe documentation (located at https://stripe.com/docs/checkout#integration-cu ...

"Enhabling tablesorter pagination to ensure that buttons always stay in sync with

I am experiencing an issue with the pagination buttons staying at the bottom of my page, even when there are only 2 entries left on the last page. Check out my table here: Is there a way to make the pagination buttons dynamically move to the top based on ...

Manipulating CSS rules using JavaScript/jQuery

My goal is to create a function that generates a grid based on table data. While the function itself seems to be working, I am encountering an issue where the classes applied are not resulting in any style changes. Below is a snippet of my function: $(doc ...

Can you include both a routerLink and a click event on the same anchor tag?

I am facing an issue with my li elements. When a user clicks on them, it should open a more detailed view in another component. However, I noticed that it takes TWO clicks to show the data I want to display. The first click opens the component with an em ...

I attempted to create a test scenario to verify that the length of the tasks array is not negative. However, when trying to test this using 'not.toBe' in the code below, an error was encountered

app.js var todos=[]; todos=['to-do one', 'to-do two']; module.exports=todos; app.test.js const todos=require('./app') test('should have a length of at least 0',()=>{ expect(todos.length).toBeGreaterThanOrEqu ...

The data in the loaded angularjs 2 select box is not showing up in the browser

I am encountering an issue with a select box that is being populated from a database. Although the select box template is loading in the browser with all the data from the database, it is not visible in the UI within a table. Controller.js: $scope.GetCvS ...

Executing JavaScript function from external SVG file globally

I am working on an HTML page that includes an external JavaScript module <script type="text/javascript" src="js/js.js"></script> and also an external SVG map called "img/map.svg". My goal is to create clickable objects on the map that will t ...

Ways to Halt observable.timer in Angular 2

As I work on Angular2's Component, I am currently implementing the following functions: export class MypageEditComponent { ngOnInit() { this.timer = Observable.timer(100, 100); this.timer.subscribe(t => { this.setFormData(); } ...

Activate Bootstrap datetimepicker by using the enter key to automatically populate the initial date

Check out the Bootstrap datetimepicker on this page: I'm trying to make it so that when the datetimepicker is first shown, pressing the enter key will hide the widget and insert the current date into the input field. I've experimented with a few ...

Why does everything seem to move in sync with the table's scrolling?

I recently had an issue resolved that fixed most of my concerns: I needed to make three separate edits, and now when I reintroduce the other two edits, they are included within the table section and scroll along with the table instead of being stuck beneat ...

What causes Vue to only update once when there are two closely timed mutations to reactive data?

Can you take a look at this simple example? export default { data() { return { name: "Amy", age: 18, }; }, computed: { combinedDataForWatching() { return { name: this.name, age: this.age, ...