Angularjs ng-model in input does not update value in controller - javascript

Can anyone explain to me why when I print console.log($scope.inputvalue) the variable is not updated with the values that I enter in the input?
Maybe I just misunderstood the meaning of ng-model, in this case, how do I pass a value from the view to controller?
(function () {
'use strict';
angular.module('LunchCheck', [])
.controller('checkiftoomuch', ['$scope', checkiftoomuch]);
function checkiftoomuch($scope){
$scope.inputvalue = "";
console.log($scope.inputvalue);
}
})();
<!doctype html>
<html lang="en" ng-app="LunchCheck">
<head>
<title>Lunch Checker</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<script src="app.js"></script>
<link rel="stylesheet" href="styles/bootstrap.min.css">
<style>
.message { font-size: 1.3em; font-weight: bold; }
</style>
</head>
<body>
<div class="container" ng-controller="checkiftoomuch">
<h1>Lunch Checker</h1>
<div class="form-group">
<input id="lunch-menu"
type="text"
placeholder="list comma separated dishes you usually have for lunch"
class="form-control"
ng-model="inputvalue">
</div>
<div class="form-group">
<button class="btn btn-default">Check If Too Much</button>
</div>
<div class="form-group message">
Total number of disches: {{ inputvalue }}
</div>
</div>
</body>
</html>

You're setting $scope.inputvalue = ""; before the console.log. But after you change the value, you need to console.log it again.
Try using:
function checkiftoomuch($scope){
$scope.inputvalue = "";
console.log($scope.inputvalue);
$scope.$watch('inputvalue', function(newValue, oldValue){
console.log(newValue);
})
}
Or add a function on your button click like:
<div class="form-group">
<button class="btn btn-default" ng-click="showValue()>Check If Too Much</button>
</div>
And in JS:
function checkiftoomuch($scope){
$scope.inputvalue = "";
console.log($scope.inputvalue);
$scope.showValue = function(){
console.log($scope.inputvalue);
}
}
AngularJS has 2-way data binding which means, the values in the view and controller are in sync always, they do not have to be passed back and forth.

Related

Script is getting executed before I press button

I'm stuck in this code this is a coursera assignment on angularjs. I'm beginner in angular js and new to stackoverflow. This is a code about to find how much a person should it. It counts the number of items and then show the result. Items are seperated by ','.
(function () {
'use strict';
angular.module('LunchCheck', [])
.controller('LunchCheckController', LunchCheckController);
LunchCheckController.$inject = ['$scope'];
function LunchCheckController($scope) {
//$scope.msg="";
//console.log($scope.calculate);
$scope.calculate="";
$scope.check = Checker($scope);
}
function Checker(string) {
var str = string.calculate;
console.log(str);
var str1 = str.split(',');
var temp = str1.length;
console.log(temp);
string.msg=message(string,temp);
}
function message(string,temp) {
if(temp > 3) {
return "Too Much!";
}
else if (temp==0) {
return "Aren`t you hungry??";
}
else {
return "Enjoy";
//console.log('Enjoy');
}
}
})();
<!doctype html>
<html lang="en">
<head>
<title>Lunch Checker</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!--<link rel="stylesheet" href="styles/bootstrap.min.css">-->
<style>
.message { font-size: 1.3em; font-weight: bold; }
</style>
<script src="angular.min.js"></script>
<script src="app.js"></script>
</head>
<body ng-app="LunchCheck">
<div class="container" ng-controller="LunchCheckController">
<h1>Lunch Checker</h1>
<div class="form-group">
<input id="lunch-menu" type="text"
placeholder="list comma separated dishes you usually have for lunch"
class="form-control" ng-model="calculate">
</div>
<div class="form-group">
<button class="btn btn-default" ng-click="check();">Check If Too Much</button>
</div>
<div class="form-group message">
<!-- Your message can go here. -->
{{msg}}
</div>
</div>
</body>
</html>
Here javascript function is getting executed before I enter any input. I want it to execute after I enter a input. Please help.
Thanks in advance.

Pushing both keys and value into an json array structure dynamically

I have angularjs front end code as follows:
function addController($scope, $http) {
$scope.tableNames = [];
$scope.addNewColumn = function(item) {
$scope.tableNames.push({})
}
}
<html ng-app>
<head>
<title></title>
<meta charset="utf-8" />
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.min.js"></script>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
</head>
<body ng-controller="addController">
<div class="col-sm-10">
<fieldset ng-repeat="item in tableNames track by $index">
<span> TextBox1:<input type="text" ng-model="item.item1" />
TextBox2:<input type="text" ng-model="item.item2" /></span>
</fieldset>
<button class="btn btn-default" ng-click="addNewColumn()">Add Colname</button>
</div>
<pre>{{tableNames|json}}</pre>
</body>
</html>
So when I enter text in the textbox1 and textbox2 it shows array of below format:
[{
"item1":"textbox1value",
"item2":"textbox2value"
}]
and also when i click addColname button and generate another textbox, values are pushed in different property as follows,it generates:
[{
"item1":"textbox1value",
"item2":"textbox2value"
},
{
"item1":"textbox1value",
"item2":"textbox2value"
}
]
but what actually i need is of structure,
[{
"textbox1value":"textbox2value",
"textbox1value":"textbox2value",
.....
}]
note(:"textboxvalue" are values entered inside textboxes.
somebody help me to get desired output. thanks in advance
This is a working code. I hope this helps :)
<html ng-app>
<head>
<title></title>
<meta charset="utf-8" />
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.min.js"></script>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<script>
function addController($scope, $http) {
$scope.tableNames = [];
$scope.getData={};
var i=-1;
$scope.addNewColumn = function (item) {
$scope.tableNames.push({})
i++;
}
$scope.addData = function(item){
if(i >= 0){
$scope.newData=[];
$scope.getData[$scope.tableNames[i].item1]=$scope.tableNames[i].item2;
$scope.newData.push($scope.getData);
}
}
}
</script>
</head>
<body ng-controller="addController">
<div class="col-sm-10">
<fieldset ng-repeat="item in tableNames track by $index">
<span> TextBox1:<input type="text" ng-model="item.item1" ng-keyup="addData()"/>
TextBox2:<input type="text" ng-model="item.item2" ng-keyup="addData()"/></span>
</fieldset>
<button class="btn btn-default" ng-click="addNewColumn()">Add Colname</button>
</div>
<pre>{{newData|json}}</pre>
</body>
</html>

AngularJS - show and hide arrow icon with glyphicon

I have a problem with the code, all I need is to hide the "NotesText" the arrow is pointing up, and after showing the "NotesText" arrow must be pointing down. I can not find the way to make this happen, please, I need help.
Basically, I need is to change the direction of the arrow agree if I need to show or hide
This is what I have .
This is HTML:
<div id="notes-controller" class="collapse in" ng-controller="NotesController">
<fieldset>
<legend class="translatable" data-i18n="Notes">Notes</legend>
<form novalidate class="simple-form">
<div class="container col-md-12" ng-show="$ctrl.param.note.visible">
<textarea class="col-md-12" ng-readonly="$ctrl.param.note.readonly" type="text" id="Notes" ng-model="$ctrl.notes.note" ng-model-options="{ getterSetter: true }" />
</div>
</form>
</fieldset>
</div>
<span type="button" class="glyphicon glyphicon-chevron-up" data-toggle="collapse" data-target="#notes-controller"></span>
This is Controller
angular.
module('notesText').
component('notesText', {
templateUrl: '/Scripts/test/notes-text/notes-text.template.html',
bindings: {
notes: '=',
param: '='
}
}).controller('NotesController', ['$scope', function ($scope) {
$scope.master = {};
$scope.update = function (user) {
$scope.master = angular.copy(user);
};
$scope.reset = function () {
$scope.user = angular.copy($scope.master);
};
$scope.reset();
}]);
This is how it looks:
enter image description here
A very Minimalistic Soln:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div class="container" ng-app="">
<textarea id="myTextArea" ng-hide="isHidden">MY TEXT</textarea>
<br>
<span class="glyphicon" ng-class="isHidden ? 'glyphicon-chevron-down' : 'glyphicon-chevron-up'" ng-click="isHidden = !isHidden;">
</span>
</div>
A more verbose Soln:
Have a look at the working example below:
Simply using ng-class to attach glyphicon-chevron-up or glyphicon-chevron-down based on expression returned by a function that checks if the textarea is visible.
angular.module("myApp", [])
.controller("myCtrl", function($scope) {
$scope.isShown = function() {
return $('#myTextArea').is(':visible');
}
$scope.hideIt = function() {
$('#myTextArea').toggle();
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div class="container" ng-app="myApp" ng-controller="myCtrl">
<textarea id="myTextArea">MY TEXT</textarea>
<br>
<span class="glyphicon"
ng-class="isShown() ? 'glyphicon-chevron-up' : 'glyphicon-chevron-down'"
ng-click="hideIt()">
</span>
</div>
Using the ng-show and ng-hide directive might be the best way to achieve this. That way you can have a scoped variable you can point to. You could also do an ng-class that if true, rotates the icon 180 degs. Either way it's up to you.
<span ng-show="$ctrl.IsToggled" type="button" class="glyphicon glyphicon-chevron-up" data-toggle="collapse" data-target="#notes-controller"></span>
<span ng-hide="$ctrl.IsToggled" type="button" class="glyphicon glyphicon-chevron-down" data-toggle="collapse" data-target="#notes-controller"></span>

Angularjs ng-repeat, ng-form and validation error

A simplified version of the code:
<!DOCTYPE html>
<html ng-app="main">
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript" src="https://code.angularjs.org/1.4.3/angular.min.js"></script>
<script>
var app = angular.module("main", []);
app.controller("TestController", function($scope) {
$scope.addresses = [{street: ""}, {street: ""}];
$scope.next = function() {
if ($scope.addressMainForm.addressForm.$valid) {
console.log("valid");
} else {
console.log("invalid");
}
$scope.addresses.push({street: ""});
};
$scope.remove = function(index) {
$scope.addresses.splice(index, 1);
};
});
</script>
</head>
<body>
<div ng-controller="TestController" style="width: 500px;">
<form name="addressMainForm">
<div ng-repeat="address in addresses">
<ng-form name="addressForm">
<input ng-model="address.street" required name="street" type="text" placeholder="street" />
<button ng-if="$index > 0" ng-click="remove($index)">REMOVE</button>
</ng-form>
<br>
</div>
</form>
<br>
<button ng-click="next()">NEXT</button>
</div>
</body>
</html>
which looks in the browser like this:
When I click "REMOVE" and then "NEXT" - javascript error is produced:
Error: $scope.addressMainForm.addressForm is undefined
Why is it undefined if there is clearly still one element remaining in the array? Everything otherwise works fine (console.log output), until all the elements are removed but the last one and "NEXT" is clicked.
When you call $scope.addressMainForm.addressForm.$valid , you are attempting to call check to see if the adressForm element is valid, but your remove function has removed the addresses entry associated with that element. So the form indeed still exists, but that call becomes illegal.
Try this:
<!DOCTYPE html>
<html ng-app="main">
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript" src="https://code.angularjs.org/1.4.3/angular.min.js"></script>
<script>
var app = angular.module("main", []);
app.controller("TestController", function($scope) {
$scope.addresses = [{street: ""}, {street: ""}];
$scope.next = function() {
if ($scope.addressMainForm.$valid) {
console.log("valid");
} else {
console.log("invalid");
}
$scope.addresses.push({street: ""});
};
$scope.remove = function(index) {
$scope.addresses.splice(index, 1);
};
});
</script>
</head>
<body>
<div ng-controller="TestController" style="width: 500px;">
<form name="addressMainForm">
<div ng-repeat="address in addresses">
<ng-form name="addressForm">
<input ng-model="address.street" required name="street" type="text" placeholder="street" />
<button ng-if="$index > 0" ng-click="remove($index)">REMOVE</button>
</ng-form>
<br>
</div>
</form>
<br>
<button ng-click="next()">NEXT</button>
</div>
</body>
</html>

angularjs view not getting updated

Here is a small self-contained html todo application using routes...
It has two views - list.html and add.html
list.html:
<div>
Add Task
<br />
<br />
<div class="container" id="tasks">
<ul>
<li ng-repeat="task in tasks">
<button ng-show="!task.done" ng-click="markTaskAsDone(task)" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-ok-circle"></span></button>
<button ng-show="task.done" ng-click="markTaskAsNotDone(task)" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-pushpin"></span></button>
<button ng-click="removeTask(task)" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-remove-circle"></span></button>
<s ng-show="task.done">{{task.desc}}</s>
<span ng-show="!task.done">{{task.desc}}</span>
</li>
</ul>
<p ng-show="tasks.length == 0">Add few tasks</p>
</div>
</div>
add.html:
<div>
<span class="glyphicon glyphicon-arrow-left"></span> Back
<h2>Add a task</h2>
<div class="form-inline">
<input type="text" data-ng-model="newTask.desc" placeholder="Enter Task..." class="form-control" />
Add
</div>
</div>
I only have one controller.
controllers = {
ToDoController: function ($scope, $timeout, $location) {
//two items in by default...
$scope.tasks = [
{ desc: 'Buy milk', done: false },
{ desc: 'Collect newspaper', done: false }
];
$scope.newTask = { desc: '', done: false };
$scope.addNewTask = function () {
$location.path('/');
console.log('a');
$scope.tasks.push($scope.newTask);
}
$scope.markTaskAsDone = function (task) {
task.done = true;
console.log($scope.tasks);
}
$scope.markTaskAsNotDone = function (task) {
task.done = false;
};
$scope.removeTask = function (task) {
$scope.tasks.splice($scope.tasks.indexOf(task), 1);
};
//called to set newTask
$scope.setNewTask = function () {
$scope.newTask = { desc: '', done: false };
};
}
};
My shell page looks like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ToDo List</title>
<!-- Bootstrap -->
<link href="Content/bootstrap.min.css" rel="stylesheet">
<link href="Content/bootstrap-theme.min.css" rel="stylesheet">
<style>
#tasks ul {
margin: 0px;
padding: 0px;
list-style: none;
font-size: large;
}
</style>
</head>
<body>
<h1>TODO App</h1>
<div data-ng-app="todoApp">
<div data-ng-view=""></div>
</div>
<script src="Scripts/jquery-1.9.0.min.js"></script>
<script src="Scripts/bootstrap.min.js"></script>
<script src="Scripts/angular.min.js"></script>
<script src="Scripts/angular-route.min.js"></script>
<script src="Scripts/todo.js"></script>
<script>
var app = angular.module('todoApp', ['ngRoute']);
app.controller(controllers);
app.config(function ($routeProvider) {
$routeProvider
.when('/list', {
controller: 'ToDoController',
templateUrl: 'partials/list.html'
})
.when('/add', {
controller: 'ToDoController',
templateUrl: 'partials/add.html'
})
.otherwise({ redirectTo: '/list' });
});
</script>
</body>
</html>
Issue:
When I load index.html its shows the list.html. The two default items I've put shows up. I click on Add and navigate to the second view (add.html), enter details and click on the Add button in that page...I navigate to the list.html view, but its still showing the old list...not the updated list...
Surely missing some api call to do the update to the view...else this page is coming from some cache. What is the correct way to do this?
ToDoController is instantiated twice and separately for your two views. To maintain 1 instance of the controller to control both views, don't declare it in your routing, but declare it on a parent tag of the views.
For instance, like this:
<div data-ng-app="todoApp" data-ng-controller="ToDoController">
<div data-ng-view></div>
</div>
Even better is to write separate controllers for each view to put the view-specific logic into, and have 1 parent controller to store values that both controllers should have access to.
Another way to share scope among isolated controllers is using $rootScope, but you should normally try to avoid using that (like you would try to avoid using global variables in any programming language).

Categories

Resources