I tried to extend the "Heros" application from the AngularJS documentation
I wanted to add the functionality of creating/adding a hero.
In the HeroList.js from this plunk I am able to add a new hero after clicking the button Add from the HeroList.html.
However, if I'm updating the input fields (let's say name) they get edited in the list as well.
For example, if I added a new hero (Captain America), click Add, and then type Robby, Captain America will be concatenated with Robbie.
(function(angular) {
'use strict';
function HeroListController($scope, $element, $attrs) {
var ctrl = this;
// This would be loaded by $http etc.
ctrl.list = [
{
name: 'Superman',
location: ''
},
{
name: 'Batman',
location: 'Wayne Manor'
}
];
ctrl.create = function(hero) {
ctrl.list.push(hero);
};
ctrl.updateHero = function(hero, prop, value) {
hero[prop] = value;
};
ctrl.deleteHero = function(hero) {
var idx = ctrl.list.indexOf(hero);
if (idx >= 0) {
ctrl.list.splice(idx, 1);
}
};
}
angular.module('heroApp').component('heroList', {
templateUrl: 'heroList.html',
controller: HeroListController,
bindings: {
onCreate: '&'
}
});
})(window.angular);
Your Problem is that you are having reference to same Hero Object so when you update the text fields it will automatically update it in the list. To Avoid this problem you can use angular.Copy()
ctrl.create = function(hero) {
ctrl.list.push(angular.copy(hero));
};
this will create separate copy to be added to the list.
here is some code you can refer https://plnkr.co/edit/?p=preview
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-forms-simple-production</title>
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
</head>
<body ng-app="formExample">
<div ng-controller="ExampleController">
<form novalidate class="simple-form">
<label>Name: <input type="text" ng-model="user.name" /></label><br />
<label>E-mail: <input type="email" ng-model="user.email" /></label><br />
Best Editor: <label><input type="radio" ng-model="user.preference" value="vi" />vi</label>
<label><input type="radio" ng-model="user.preference" value="emacs" />emacs</label><br />
<input type="button" ng-click="reset()" value="Reset" />
<input type="submit" ng-click="update(user)" value="Save" />
</form>
<pre>user = {{user | json}}</pre>
<pre>master = {{master | json}}</pre>
</div>
<script>
angular.module('formExample', [])
.controller('ExampleController', ['$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();
}]);
</script>
</body>
</html>
<!--
Copyright 2018 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
-->
Related
I am working on school project using angularjs, I don't know why I'm getting this Error: $controller:ctrlreg A controller with this name is not registered.
index.html:
...
<div ng-controller="medscontroller">
<ul>
<li ng-repeat="med in meds | filter:{nom:nom} | orderBy:order">{{med.nom}}</li>
</ul>
</div>
<script >
function medscontroller($scope){
$scope.meds=[
{"nom":"aspirine", "prix":"20"},
{"nom":"doliprane","prix":"15"},
{"nom":"da", "prix":"15"}
];
console.log($scope);
}
</script>
You cannot simply define a controller function like above.
In order for a controller to work, you have to do the following things.
Create an angular app with
var app = angular.module('myApp', []);
Deine a controller for that app with.
app.controller('myCtrl', function($scope) { });
Find a working example here.
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.firstName = "John";
$scope.lastName = "Doe";
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
First Name: <input type="text" ng-model="firstName"><br>
Last Name: <input type="text" ng-model="lastName"><br>
<br>
Full Name: {{firstName + " " + lastName}}
</div>
I have created a filter that searches the view data based on the input value(Single value) entered in the search field.
Controller -
patchingApp.controller('patchingController', function ($scope, $state, patchingServices, Excel, $timeout) {
'use strict';
$scope.searchData = '';
$scope.searchForm = {};
View -
<div class="row">
<div class="col-md-10">
<span class="search-filter"> On-Screen Filter: <input ng-model="searchText" /></span>
</div>
</div>
<tbody class="tbody-class">
<tr ng-repeat="patching in main_data_table.message | filter:searchText" >
New Requirement - I should be able to enter multiple values in the search field separated by a comma.
Example - {patch, debug}
You can write a custom filter to do this. Modify the below code to your requirements
var app = angular.module('store', []);
app.controller('StoreController', ['$scope', function($scope) {
$scope.searchText="";
$scope.friends = [{
name: 'John'
}, {
name: 'Mary'
}, {
name: 'Mike'
}, {
name: 'Adam'
}, {
name: 'Julie'
}, {
name: 'Juliette'
}];
}]);
app.filter('fill', function() {
return function(input,val) {
if(val!=undefined){
var out=[];
var filterVal = val.split(",");
if (filterVal.length > 1) {
for (var i = 0; i < filterVal.length; i++) {
for(var j=0;j<input.length;j++){
if (input[j].name == filterVal[i]) out.push(input[j]);
}
}
return out;
}
}
}
});
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-filter-filter-production</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>
<body ng-app="store" ng-controller="StoreController">
<label>Search: <input ng-model="searchText"></label>
<table id="searchTextResults">
<tr><th>Name</th></tr>
<tr ng-repeat="friend in friends" ng-if="searchText.indexOf(',')==-1">
<td>{{friend.name}}</td>
</tr>
<tr ng-repeat="friend in friends | fill:searchText track by $index" ng-if="searchText.indexOf(',')>-1">
<td>{{friend.name}}</td>
</tr>
</table>
</body>
</html>
i tried to make login form with angular js
i have list of user in json file but i can't comapre with the input text from login form
User.json :
[{
"username": "user1",
"password": "pass1"
}, {
"username": "user2",
"password": "pass2"
}, {
"username": "user3",
"password": "pass3"
}, {
"username": "user4",
"password": "pass4"
}]
script.js
var app1 = angular.module('app1', []);
var app2 = angular.module('app2', []);
var app = angular.module('app', ['app1', 'app2']);
app1.controller('jsonCtrl', function($scope, $http) {
$http.get('data.json')
.then(function(res) {
$scope.users = res.data;
});
});
app2.controller('formCtrl', function($scope) {
$scope.login = function() {
if ($scope.username == 'test' && $scope.password == 'test') {
alert('valid username/password ' + $scope.username);
alert('user from json ' + $scope.users);
} else {
alert('invalid username/password ' + $scope.username);
}
};
});
index.html
<!DOCTYPE html>
<html lang="en">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="script.js"></script>
<body ng-app="app">
<div ng-controller="formCtrl">
<form name="form">
First Name:<br>
<input type="text" ng-model="username"><br>
Last Name:<br>
<input type="text" ng-model="password">
<br><br>
<button ng-click="login()">LOGIN</button>
</form>
</div>
<div ng-controller="jsonCtrl">
<ul>
<li ng-repeat="user in users">
{{user.username}} / {{user.password}}
</li>
</ul>
</div>
</body>
</html>
the problem is replace if ($scope.username == 'test' && $scope.password == 'test') with anything compare with json
this my code : Plunker
You were using two different scopes across application. I moved all your markup under the same controller, so that is more simple manage the bindings.
Take a look at this plnkr
var app = angular.module('app', []);
app.controller('formCtrl', function($scope, $http) {
$http.get('data.json')
.then(function(res) {
$scope.users = res.data;
});
$scope.login = function() {
var u = $scope.users.filter((item) => {
return item.username == $scope.username;
});
if (u[0] && u[0].password == $scope.password) {
alert('correct');
} else {
alert('wr0ng');
}
};
});
<div>
<form name="form">
First Name:
<br>
<input type="text" ng-model="username">
<br> Last Name:
<br>
<input type="text" ng-model="password">
<br>
<br>
<button ng-click="login()">LOGIN</button>
</form>
</div>
<div>
<ul>
<li ng-repeat="user in users">
{{user.username}} / {{user.password}}
</li>
</ul>
</div>
First of all, you should not authenticate user using clear text like that. Your server should do it with hashing table without knowing what is the real password.
Http.get is not synchronous which means that your application will continue its path without waiting for your data. In your plunker your formCtrl doesnt have access to jsonCtrl scope.
You should load your data in a service because it is initialised only once compared to the controller who are initialised everytime you load the page.
Finally you should start by looking at ui.router resolve, it allow you to load your data to your service before the page is displayed which will allow you to compare later.
// SERVICES
app.factory('searchFactory', ['$http', function($http) {
return $http.post("/api", { tag: "food" });
}]);
// CONTROLLERS
app.controller('MainController', ['$scope', 'searchFactory', function ($scope, searchFactory) {
$scope.submit = function () {
searchFactory.then(function(response) {
$scope.recipeData = JSON.parse(response.data);
});
};
// HTML
<form ng-submit="submit()">
<div class="form-group">
<input type="text" ng-model="recipeTag" class="form-control" />
<input type="submit" class="btn btn-primary" value="Find Recipes" />
</div>
</form>
Does anyone know how I can use $scope.recipeTag from ng-model to replace "food" in the factory? I need to be able to pass the form input as a parameter into the factory.
you need to create a funtion that expects a parameter in your factory.
Example:
var factory= {
post: function(customTag) {
return $http.post("/api", { tag: customTag });
}
};
return factory;
Okay so I am trying to learn how to create a modular angular app, but I don't really know how it would look. Based on my code what would I need to do to make it modular? My app is pretty small but I still want to try and get the idea down as for how to create a modular app so that I can just do that from the beginning the next time I create a web app. I didn't include the css as it seems irrelevant for this question. Help would be greatly apprciated.
index.html
<!DOCTYPE html>
<html>
<head>
<header>To do App</header>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>To do App</title>
<script type='text/javascript' src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"> </script>
<script type='text/javascript' src="//use.edgefonts.net/vast-shadow:n4:all.js"></script>
<script type='text/javascript' src="//use.edgefonts.net/vast-shadow:n4:all;megrim.js"></script>
<script type='text/javascript' src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
<script type='text/javascript' src="js/index.js"></script>
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<div ng-app="demoApp">
<script type="text/ng-template" id="partials/edit-form.html">
<div ng-show="todo.editMode">
<input ng-model="todo.text" />
<button ng-click="save(todo)">save</button>
</div>
</script>
<div class="todo-wrapper" ng-controller="todoCtrl">
<h2>You have <span class="emphasis">{{getTotalTodos()}}</span> tasks</h2>
<input class="search-input" type="text" ng-model="searchText" placeholder="enter search term" />
<ul>
<li ng-repeat="todo in todos | filter: searchText">
<span>{{todo.text}}: {{todo.date_created}}</span>
<div ng-include="'partials/edit-form.html'"></div>
<button class="clear-btn" ng-click="removeTask(todo)">Remove</button>
<button class="clear-btn" ng-click="editTask(todo)">Edit</button>
</li>
</ul>
<form>
<input class="add-input" placeholder="task name" type="text" ng-model="text" ng-model-instant />
<button class="add-btn" ng-click="addTask()"><h2>Add</h2></button>
</form>
</div>
</body>
</html>
index.js
angular.module('demoApp', [])
.controller('todoCtrl', TodoCtrl);
function TodoCtrl($scope) {
$scope.todos = [{
id: 1,
text: 'Mow the lawn',
selected: false
}, {
id: 2,
text: 'Wash the car',
selected: false
}];
$scope.id = $scope.todos.length + 1; //later create an uuid
$scope.getTotalTodos = function () {
return $scope.todos.length;
};
$scope.addTask = function () {
$scope.todos.push({
editMode: false,
text: $scope.text,
id: $scope.id,
date_created: Date.now,
selected: false
});
$scope.text = '';
$scope.id = '';
};
$scope.removeTask = function (todo) {
/*$scope.todos = _.filter($scope.todos, function (todo) {
return !todo.selected;
});*/
$scope.todos.pop(todo);
//update server now with ngResource...
};
$scope.showDetails = function (task_id) {
var found = $filter('filter')($scope.todos, {
id: task_id
}, true);
if (found.length) {
$scope.selected = JSON.stringify(found[0]);
} else {
$scope.selected = 'Not found';
}
}
$scope.editTask = function(todo) {
todo.editMode = true;
console.log(todo);
};
$scope.save = function(todo) {
todo.editMode = false;
// update data at server now too. $scope.todos is up-to-date
}
$scope.updateTask = function (task_id) {
// search $scope.todos for the item to update
var indexOfTask;
for (var i = 0; i < $scope.todos.length; i++) {
if ($scope.todos[i].id === $scope.id) indexOfTask = i;
$scope.todos[i] = todo;
$scope.todos.push();
$scope.text = '';
$scope.id = '';
}
// update the todo
};
}
Essentially just make a new file for every angular whatever (factory, controller, directive, etc.)
I use this syntax
angular.module('myapp.functionName.type', [])
.type('functionName',);
Then in your app.js, in your case index.js
angular.module('myapp', ['myapp.functionName.type', ... ]) ;