AngularJS date in controller undefined - angularjs

I'm trying to add a date that defaults to the current day to my page. Below is the angular script for this but when I click add day I get error of undefined? I don't understand I believe it's been defined correctly.
$scope.today= new Date();
$scope.add = {};
if($scope.today){
var today= new Date($scope.today)
$scope.add.today=
today.getFullYear()+'-'+(today.getMonth() + 1)+'-'+today.getDate();
}else{
$scope.add.today= null;
}
<div class="form-group col-sm-4">
<label for="Date">Date</label>
<input type="date" class="form-control" name="add_row_today" id="add_row_today" ng-model="today">
</div>
This is what my code looks like.
this is the stack trace from console
TypeError: Cannot set property 'today' of undefined
at m.$scope.add_list (angularScripts.js?v=1.3:8741)
at fn (eval at compile (_bower.js?v=1.2:10467), <anonymous>:4:220)
at b (_bower.js?v=1.2:10360)
at e (_bower.js?v=1.2:10510)
at m.$eval (_bower.js?v=1.2:10379)
at m.$apply (_bower.js?v=1.2:10380)
at HTMLInputElement.<anonymous> (_bower.js?v=1.2:10510)
at HTMLInputElement.dispatch (_bower.js?v=1.2:5201)
at HTMLInputElement.elemData.handle (_bower.js?v=1.2:5009)

You have a typo.
property 'today' of undefined means something has .today, which doesn't exists. In your case it's either $scope.add or $scope.edit
I think while changing your code, you forgot to replace one of them. Try changing:
$scope.edit.today = null;
to
$scope.add.today = null;
Or initialise it, if you are missing it with $scope.edit = {};
Given your edited code, you have a working solution
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.today = new Date();
$scope.add = {};
if ($scope.today) {
var today = new Date($scope.today)
$scope.add.today =
today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate();
} else {
$scope.add.today = null;
}
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<div class="form-group col-sm-4">
<label for="Date">Date</label>
<input type="date" class="form-control" name="add_row_today" id="add_row_today" ng-model="today">
</div>
</div>
</body>
</html>

Related

Add ng-model value in false condition of ng-attr-title

How to do I add mainCtrl.header.Version in the string text if the condition in ng-attr-title is false?
HTML
<label class="form-control" ng-attr-title="{{mainCtrl.header.Version == 0 ? 'This form has not yet been submitted for approval' : 'This form has been submitted for approval {{mainCtrl.header.Version}} times'}}">{{mainCtrl.header.Version}}</label>
The syntax is :
ng-attr-title="{{mainCtrl.header.Version == 0 ? 'This form has not yet been submitted for approval' : 'This form has been submitted for approval ' + mainCtrl.header.Version + ' times'}}"
ng-attr-title displays the string it is given, so you have to use {{ expr }}.
To test your expression I'd advice you to write <pre>{{ your expression | json }}</pre> to see what is the result.
You can achieve it from JS controller side. Take a variable title check if version is 0 then assign title you want. And if version is > than 0 then concat the version with title message. Please consider the following code snippet.
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl as mainCtrl">
<label class="form-control" ng-attr-title="{{mainCtrl.title}}">
{{mainCtrl.header.Version}}
</label>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
var mainCtrl = this;
mainCtrl.header = {"Version":0};
if( mainCtrl.header.Version == 0 )
{
mainCtrl.title = "This form has not yet been submitted for approval";
}
else
{
mainCtrl.title = "This form has not yet been submitted for " +mainCtrl.header.Version+" approval";
}
});
</script>
</body>
</html>
you can do it by calling a function like that:
var app = angular.module('app', []);
app.controller('htmlTitle', ['$scope','$http', function($scope, $http){
$scope.mainCtrl = {
header: {
Version: 0
}
};
$scope.get_title = function(){
if($scope.mainCtrl.header.Version == 0){
return 'This form has not yet been submitted for approval';
}
else{
return 'This form has been submitted for approval ' + $scope.mainCtrl.header.Version + ' times';
}
}
}]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="htmlTitle">
<label class="form-control" title="{{get_title()}}" >{{mainCtrl.header.Version}}</label>
</div>
</div>
and here is a codepen.

Dynamic Angular Js Not working via innerHTML

If I add a row with Dynamic Angular JS variable, it is not working.
Below is my code. Please help me let know the issue.
Also please note that the inner HTML in my original code is 600 lines long. In this example I have used simple div to simplify.
<div data-ng-init="quantity_r=1;price_r=5">
<h2>Cost Calculator Quantity:</h2>
<input type="number" ng-model="quantity_r"> Price: <input type="number" ng-model="price_r">
<div>
Total in dollar: {{quantity_r * price_r}}
</div>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<script>
var app = angular.module('myApp', []);
app.controller('AppCtrl', function($scope) {
});
</script>
<script>
var app = angular.module('myApp1', []);
app.controller('AppCtrl', function($scope) {
angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) {
$scope.a = 1;
$scope.b = 2;
});
});
function replicateRegion() {
var table = document.getElementById("idTable");
var lastRow = table.rows.length;
var row = table.insertRow(lastRow);
var cell1 = row.insertCell(0);
var sHTML =document.getElementById("idTableTD1").innerHTML;
sHTML=sHTML.replace("_r", "_r" + lastRow.toString());
sHTML=sHTML.replace("Cost Calculator Quantity:", "Cost Calculator Quantity: Row Added " + lastRow.toString());
cell1.innerHTML = sHTML;
}
</script>
<div id="id1" ng-app="myApp" ng-controller="AppCtrl">
<button onclick="replicateRegion()">insert Row</button>
<table id="idTable">
<tr><td id="idTableTD1">
<div data-ng-init="quantity_r=1;price_r=5">
<h2>Cost Calculator Quantity:</h2>
<input type="number" ng-model="quantity_r"> Price: <input type="number" ng-model="price_r">
<div>
Total in dollar: {{quantity_r * price_r}}
</div>
</td></tr>
</table>
</div>
</body>
</html>
Only the first row which is static has the correct output. The rows added after button-click "Insert Row" have the problematic Angular JS output. Please help.
You need to add the code for replicateRegion() function inside the AngularJS controller and use the $compile service to bind the dynamically generated HTML into the AngularJS DOM.
var myapp = angular.module('myApp', []);
myapp.controller('AppCtrl', function ($compile, $scope) {
$scope.a = 1;
$scope.b = 2;
$scope.replicateRegion = function(){
var table = document.getElementById("idTable");
var lastRow = table.rows.length;
var row = table.insertRow(lastRow);
var template = `<div data-ng-init="quantity_r=1;price_r=5">
<h2>Cost Calculator Quantity:</h2>
<input type="number" ng-model="quantity_r"> Price: <input type="number" ng-model="price_r">
<div>
Total in dollar: {{quantity_r * price_r}}
</div>
</div>`;
var cell1 = row.insertCell(0);
template=template.replace(/_r/g, "_r" + lastRow.toString());
template=template.replace("Cost Calculator Quantity:", "Cost Calculator Quantity: Row Added " + lastRow.toString());
cell1.innerHTML = template;
$compile(cell1)($scope); //Now compile it to render the directive.
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div id="id1" ng-app="myApp" ng-controller="AppCtrl">
<button ng-click="replicateRegion()">insert Row</button>
<table id="idTable">
<tr><td id="idTableTD1">
<div data-ng-init="quantity_r=1;price_r=5">
<h2>Cost Calculator Quantity:</h2>
<input type="number" ng-model="quantity_r"> Price: <input type="number" ng-model="price_r">
<div>
Total in dollar: {{quantity_r * price_r}}
</div>
</div>
</td></tr>
</table>
</div>
Also notice that var template that specifies a generic template that should be inserted in the HTML dynamically on click. It is always a good practice to specify a static HTML template instead of extracting the generated HTML from the page and using that, which you have done.
When you add markup manually, like
document.getElementById('idTableTD1').innerHTML= '<div dynamic></div>'
you are bypassing all AngularJS code. You should do it rather as this:
angular.element("#idTableTD1").html('<div dynamic></div>');
may be this will help.

AngularJs can't run a method

I am a beginner angularjs user, but i have to learn it for my new job and I thought I could practice a bit. So I did a simple string reverse method and I thought I could make a simple calculator (exactly, only sum). Here is my code. I made 2 modules, 2 controllers and the first one is working fine, but the calculator isn't. However I made a simple site, where only the calc code is, and it works fine and I don't understand why it works, but doesn't work if 2 modules are on the same site.(Yeah, i'm a very beginner). Thank you for your help.
<!DOCTYPE html>
<html lang="en">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"> </script>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div ng-app="MyApp" ng-controller="myController">
<center>
<input type="text" ng-model="myString" placeholder="Enter text"/>
<p>Input: {{myString }}</p>
<p>Filtered input: {{getReverse()}}</p>
</center>
</div>
<br><br>
<center>
<div ng-app="MyCalc" ng-controller="myCalculate">
<input type="text" ng-model="firstNumber"><br>
<input type="text" ng-model="secondNumber"><br>
<p> Result: {{getResult()}}</p>
</div>
</center>
<script>
var reverse = angular.module("MyApp", []);
var calc = angular.module("MyCalc",[]);
reverse.controller('myController',function($scope){
$scope.myString = "";
$scope.getReverse = function(){
return $scope.myString.split("").reverse().join("");
}
});
calc.controller('myCalculate',function($scope){
$scope.firstNumber = 0;
$scope.secondNumber = 0;
$scope.getResult = function(){
return Number($scope.firstNumber)+Number($scope.secondNumber);
}
});
</script>
ng-app directive can be used just one time in page.
only one AngularJS application can be auto-bootstrapped per HTML document. The first ngApp found in the document will be used to define the root element to auto-bootstrap as an application. To run multiple applications in an HTML document you must manually bootstrap them using angular.bootstrap instead. (https://docs.angularjs.org/api/ng/directive/ngApp)
But you can bootstrap manually your app. Affect id on div that contains an angular app and add this to your script (https://plnkr.co/edit/ZTW7mXx3iXm803xdYod1?p=preview):
angular.bootstrap(document.getElementById('reverse'), ['MyApp']);
angular.bootstrap(document.getElementById('calc'), ['MyCalc']);
But I agree with Vikash, create more modules and less app :)
Normally, you should not use 2 angular app in a web page.
If you need to use different module, just make one depend on another.
Let's say your main module is MyApp and you need MyCalc's function, you do it like this (JsFiddle):
var calc = angular.module("MyCalc",[]);
calc.controller('myCalculate',function($scope){
$scope.firstNumber = 0;
$scope.secondNumber = 0;
$scope.getResult = function(){
return Number($scope.firstNumber)+Number($scope.secondNumber);
}
});
// Make MyApp module depend on MyCalc
var reverse = angular.module("MyApp", ["MyCalc"]);
reverse.controller('myController',function($scope){
$scope.myString = "";
$scope.getReverse = function(){
return $scope.myString.split("").reverse().join("");
}
});
And then in the HTML:
<body ng-app="MyApp">
<div ng-controller="myController">
<center>
<input type="text" ng-model="myString" placeholder="Enter text"/>
<p>Input: {{myString }}</p>
<p>Filtered input: {{getReverse()}}</p>
</center>
</div>
<br><br>
<center>
<div ng-controller="myCalculate">
<input type="text" ng-model="firstNumber"><br>
<input type="text" ng-model="secondNumber"><br>
<p> Result: {{getResult()}}</p>
</div>
</center>
</body>
P/s: If you really need to bootstrap 2 angular app in the same web page, you need to bootstrap it manually (JsFiddle):
angular.bootstrap(document.getElementById('calc'), ['MyCalc']);
calc is the id of the element you need to bootstrap the second app on
<div id="calc" ng-controller="myCalculate">
use ng-module instead of ng-app because ng-app can be used with one module in one page.
<div ng-module="MyModuleA">
<h1>Module A</h1>
<div ng-controller="MyControllerA">
{{name}}
</div>
<div ng-module="MyModuleB">
<h1>Just Module B</h1>
<div ng-controller="MyControllerB">
{{name}}
</div>
var moduleA = angular.module("MyModuleA", []);
moduleA.controller("MyControllerA", function($scope) {
$scope.name = "Bob A";
});
var moduleB = angular.module("MyModuleB", []);
moduleB.controller("MyControllerB", function($scope) {
$scope.name = "Steve B";
});
Use angular ng-modules to achieve this
here is the working [link] [1]
[1] http://jsfiddle.net/j5jzsppv/111/
<div ng-modules="MyModuleA, MyModuleB">
<div ng-controller="myController">
<input type="text" ng-model="myString" placeholder="Enter text"/>
{{myString}}
<p>Filtered input: {{getReverse()}}</p>
</div>
<div ng-controller="myCalculate">
<input type="text" ng-model="firstNumber"><br>
<input type="text" ng-model="secondNumber"><br>
<p> Result: {{getResult()}}</p>
</div>
var reverse = angular.module("MyModuleA", []);
var calc = angular.module("MyModuleB", []);
reverse.controller('myController', function ($scope) {
$scope.myString = "";
$scope.getReverse = function () {
return $scope.myString.split("")
.reverse()
.join("");
}
});
calc.controller('myCalculate', function ($scope) {
$scope.firstNumber = 0;
$scope.secondNumber = 0;
$scope.getResult = function () {
return Number($scope.firstNumber) + Number($scope.secondNumber);
}
});

Set attribute for dynamically added each elements

How can i set 'type attribute' for each added dynamic buttons?
In below code, label names were changing perfectly,, and also i could able to set 'type attribute' to first added button, but remaining button types are not changing properly.. can u pls check it out and solve this to me pls ..
Working DEMO
Updated:
var app = angular.module('myapp', ['ngSanitize']);
app.controller('MainCtrl', function($scope, $compile) {
var counter = 0;
$scope.buttonFields = [];
$scope.add_Button = function(index) {
$scope.buttonFields[counter] = {button: 'Submit'};
var buttonhtml = '<div ng-click="selectButton(buttonFields[\'' + counter + '\'])"><button id="button_Type">{{buttonFields[' + counter + '].button}}</button>//click//</div>';
var button = $compile(buttonhtml)($scope);
angular.element(document.getElementById('add')).append(button);
$scope.changeTosubmit = function () {
var el = document.getElementById("button_Type");
el.setAttribute("type", "submit");
compile(el);
};
$scope.changeToreset = function () {
var el = document.getElementById("button_Type");
el.setAttribute("type", "reset");
compile(el);
};
$scope.changeTocancel = function () {
var el = document.getElementById("button_Type");
el.setAttribute("type", "cancel");
compile(el);
};
++counter;
};
$scope.selectButton = function (val) {
$scope.buttonField = val;
$scope.showButton_Types = true;
};
});
<!DOCTYPE html>
<html ng-app="myapp">
<head>
<script src="https://code.angularjs.org/1.4.8/angular.js"></script>
<script src="https://code.angularjs.org/1.5.0-rc.0/angular-sanitize.min.js"></script>
</head>
<body ng-controller="MainCtrl">
<button ng-click="add_Button($index)">Add Buttons</button>
<hr>
<div id="add"></div>
<form ng-show="showButton_Types">
<div>
<label>Button Name(?)</label><br/>
<input ng-model="buttonField.button">
</div>
<div>
<label>change button types(?)</label><br/>
<input ng-click="changeTosubmit()" name="submit" type="radio"> Submit
<input ng-click="changeToreset()" name="submit" type="radio"> Reset
<input ng-click="changeTocancel()" name="submit" type="radio"> Cancel
</div>
</form>
</body>
</html>
You're selecting "all the buttons" via document.getElementById("button_Type"). That's the problem: getElementById returns the first item it can find with the given id.
Try to use document.querySelectorAll() instead (which will always return an array).

broadcasting model changes

I'm trying to set up a little POC to see whether or not angular would work for something I'm in the middle of.
I set up a REST server which I am able to CRUD with via angular. However, as the documentation and tutorials out there are so all over the place (read: SUPER inconsistent), I am not sure that the behavior I'm not seeing is the result of incorrect code or it's not something I can do like this.
I've gleaned from the docs that two-way binding is available, but it isn't clear how it works. NB I've read dozens of articles explaining how it works at a low level a'la https://stackoverflow.com/a/9693933/2044377 but haven't been able to answer my own question.
I have angular speaking to a REST service which modifies a sql db.
What I am wondering about and am trying to POC is if I have 2 browsers open and I change a value in the db, will it reflect in the other browser window?
As I said, I have it updating the db, but as of now it is not updating the other browser window.
app.js
angular.module('myApp', ['ngResource']);
var appMock = angular.module('appMock', ['myApp', 'ngMockE2E']);
appMock.run(function($httpBackend) {});
controllers.js
function MainCtrl($scope, $http, $resource) {
$scope.message = "";
$scope.fruits = [];
$scope.fruit = {};
$scope.view = 'partials/list.html';
var _URL_ = '/cirest/index.php/rest/fruit';
function _use_$resources_() { return false; }
function _fn_error(err) {
$scope.message = err;
}
$scope.listFruits = function() {
$scope.view = 'partials/list.html';
var fn_success = function(data) {
$scope.fruits = data;
};
$http.get(_URL_).success(fn_success).error(_fn_error);
}
function _fn_success_put_post(data) {
$scope.fruit = {};
$scope.listFruits();
}
function createFruit() {
$http.post(_URL_, $scope.fruit).success(function(data){
$scope.listFruits()
}).error(_fn_error);
}
function updateFruit() {
$http.post(_URL_, $scope.fruit).success(_fn_success_put_post).error(_fn_error);
}
function deleteFruit() {
$http.put(_URL_, $scope.fruit).success(_fn_success_put_post).error(_fn_error);
}
$scope.delete = function(id) {
if (!confirm("Are you sure you want do delete the fruit?")) return;
$http.delete("/cirest/index.php/rest/fruit?id=" + id).success(_fn_success_put_post).error(_fn_error);
}
$scope.newFruit = function() {
$scope.fruit = {};
$scope.fruitOperation = "New fruit";
$scope.buttonLabel = "Create";
$scope.view = "partials/form.html";
}
$scope.edit = function(id) {
$scope.fruitOperation = "Modify fruit";
$scope.buttonLabel = "Save";
$scope.message = "";
var fn_success = function(data) {
$scope.fruit = {};
$scope.fruit.id = id;
$scope.view = 'partials/form.html';
};
$http.get(_URL_ + '/' + id).success(fn_success).error(_fn_error);
}
$scope.save = function() {
if ($scope.fruit.id) {
updateFruit();
}
else {
createFruit();
}
}
$scope.cancel = function() {
$scope.message = "";
$scope.fruit = {};
$scope.fruits = [];
$scope.listFruits();
}
$scope.listFruits();
}
MainCtrl.$inject = ['$scope', '$http', '$resource'];
list.html
{{message}}
<hr/>
New Fruit
<ul ng-model="listFruit">
<li ng-repeat="fruit in fruits">
id [{{fruit.id}}] {{fruit.name}} is {{fruit.color}}
[X]
</li>
</ul>
index.html
<!doctype html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="utf-8">
<title>FRUUUUUUUUUUUUUUUUUUUUUUUUUUUIT</title>
<link rel="stylesheet" href="css/bootstrap/css/bootstrap.css"/>
</head>
<body>
<div class="navbar">NAVBARRRRRRRRRRR</div>
<div class="container">
<div class="row">
<div ng-controller="MainCtrl">
<button ng-click="listFruits()">ListFruit()</button>
<button ng-click="cancel()">Cancel()</button>
<ng-include src="view"></ng-include>
</div>
</div>
</div>
<!-- In production use:
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js"></script>
-->
<script src="lib/angular/angular.js"></script>
<script src="lib/angular/angular-resource.js"></script>
<script src="js/app.js"></script>
<script src="js/services.js"></script>
<script src="js/controllers.js"></script>
<script src="js/filters.js"></script>
<script src="js/directives.js"></script>
</body>
</html>
form.html
<h3>{{fruitOperation}}</h3>
<hr/>
<form name="fruitForm">
<input type="hidden" name="" ng-model="fruit.id" />
<p><label>name</label><input type="text" name="name" ng-model="fruit.name" value="dfgdfgdfg" required="true" /></p>
<p><label>color</label><input type="text" name="color" ng-model="fruit.color" value="fruit.color" required="true" /></p>
<hr/>
<input type="submit" ng-click="save()" value="{{buttonLabel}}" /> <button ng-click="cancel()">Cancel</button>
</form>
Thanks for any insight or pointers.
Two-way binding refers to changes occurring in your controller's scope showing up in your views and vice-versa. Angular does not have any implicit knowledge of your server-side data. In order for your changes to show up in another open browser window, for example, you will need to have a notification layer which pushes changes to the client via long polling, web sockets, etc.

Resources