I have a simple web app that lists users by first name and the city they live in.
When the user clicks their name or city, the elements will be replaced by two input elements. One for the name and the second is for the city they live in. The input element(s) will help the user update their first name and city. Simple AngularJS Directive DOM Manipulation.
The problem I have is that when someone clicks the name or the city element, the bind text does not show up in the input element until you click the save update button in my info directive.
This is the HTML:
<!DOCTYPE HTML>
<html id="ng-app" ng-app="app">
<head>
<meta charset="UTF-8">
<title>JS</title>
</head>
<body>
<div ng-controller="UserController">
<div>
Search:
<input placeholder="search customers" data-ng-model="name" />
</div>
<div >
<h4>Customers</h4>
<ul>
<li ng-repeat="cust in customers | filter:name" >
<!-- My Info Directive -->
<info update="updateCustomer(this)" name="cust.name" city="cust.city"></info>
</li>
</ul>
</div>
<div>
Name: <input type="text" ng-model="newCustomer.name" /><br />
City: <input type="text" ng-model="newCustomer.city" /><br />
<button ng-click="addCustomer()" >Add New Customer</button>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
<script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script type="text/javascript" src="main.js"></script>
</body>
</html>
This is the JavaScript (main.js):
var app = angular.module("app",[])
.controller('UserController',function ControllerOne($scope){
$scope.customers = [
{name:"Milo",city:"London"},
{name:"John", city:"New York"},
{name:"Alfred",city:"Oslo"}
];
$scope.addCustomer = function (){
$scope.customers.push({name:$scope.newCustomer.name, city:$scope.newCustomer.city});
$scope.newCustomer.name = $scope.newCustomer.city = "";
};
$scope.updateCustomer = function(ele){
console.log("Name: " + ele.name + " City: " + ele.city);
}
})
.directive("info",function($compile){
return {
restrict :"E",
scope:{
name:"=",
city:"=",
update:"&"
},
template:"<div>{{name}}-{{city}}</div>",
link:function(scope,element,attrs){
element.bind("click",function(){
var html = "<input name='name' ng-model='name'/><input name='city'ng-model='city'/><button ng-click='update(this)'>Save Update</button>";
var dataScoped = $compile(html)(scope);
element.replaceWith(dataScoped);
});
}
}
});
click event is async. It means your scope doesn't know about model changes. Just wrap these two lines:
var dataScoped = $compile(html)(scope);
element.replaceWith(dataScoped);
with a scope.$apply:
scope.$apply(function(){
var dataScoped = $compile(html)(scope);
element.replaceWith(dataScoped);
});
Working: http://plnkr.co/edit/Z72AfK?p=preview
Related
I have an input text box where user enter model number and the model number must be displayed in multiple data lists when user click add button. The user has must also have the option to remove the selected model number in the multiple data lists. I have created the HTML code and Javascript code, but the javascript is not adding.
What is is the best approach to my problem? I'm very newbie to javascript.
Hey is my code:
<html lang=en>
<head>
<title>Add To Datalist</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="bootstrap_3.3.7/css/bootstrap.min.css" rel="stylesheet">
<link href="bootstrap_3.3.7/fonts/font-awesome.min.css" rel="stylesheet" >
</head>
<body>
<div class="container">
<div class="content">
<br/>
<div class="col-sm-6">
<legend>Compatible Devices </legend>
<input type="text" class="form-control" id="modelNo" name="modelNo" placeholder="Enter Name Here"><br/>
<button class="btn btn-info">Add </button>
<button class="btn btn-danger">Remove</button>
</div>
<div class="col-sm-6">
<div class="listfromPopulatedModelNumber" id="listfromPopulatedModelNumber">
<select id="listfromPopulatedModelNo" multiple="multiple" col=10 rows=10>
<option></option>
<option></option>
<option></option>
</select>
</div>
</div>
</div>
</div>
</body>
JavaScript Code:
<script type="text/javascript">
$(document)
.ready(
function() {
var count = 2;
$("#addModNo")
.click(
function() {
$('#listfromPopulatedModelNo')
.last()
.after(
'#modelNo');
count++;
});
$("#removeModNo").click(function() {
$('#modelNumber > option:selected').remove();
count--;
});
});
</script>
All help will be appreciated.
This should work for you. I have updated solution for you here Updated Solution
$(document).ready(function(){
$('#addModNo').click( function(){
var input = $("input[name='modelNo']").val();
console.log(input);
$('#listfromPopulatedModelNo').append("<option value='"+$(this).val()+"'>"+ input +"</option>");
});
$('#removeModNo').click(function(){
$('option:selected').each( function() {
var input = $("input[name='modelNo']").val();
$('#listfromPopulatedModelNo').append("<option value='"+$(this).val()+"'>"+ input +"</option>");
$(this).remove();
});
});
});
How to error proof JavaScript from item list by entering the same item or no item. Please help me guys of been researching for days StackOverFlow is my last hope. Any Help will be appreciated.`Thanks guys
var app = angular.module('myApp',[]);
app.controller('SportController', function($scope) {
$scope.newItem;
//List Sport
$scope.sports = ['Football', 'Basketball', 'Hockey', 'Soccer'];
//Remove Sport
$scope.addItem = function(){
$scope.sports.push($scope.newItem);
$scope.newItem = '';
}
//Remove Sport
$scope.removeItem = function(item){
var idx = $scope.sports.indexOf(item);
$scope.sports.splice(idx,1);
}
});
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
<link rel="stylesheet" href="css/style.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>
<script src="js/app.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller='SportController'>
<h1>Sport List</h1>
<div>
<form ng-submit="addItem()">
<div>
<input type="text" ng-model="newItem" placeholder"Add Sport"/>
<button type="submit">Save</button>
</div>
</form>
</div>
<p> {{ newItem }}</p>
<div>
<h4>Sports {{ sports.length }}</h4>
<table>
<tr ng-repeat="spor in sports">
<td>{{spor}}</td>
<td>
<button ng-click="removeItem(spor)">×</button>
</td>
</tr>
</table>
</div>
<!--End of div--->
</body>
</html>
Block the UI from being able to submit.
Or use a simple if check...
$scope.addItem = function(item){
//blank item
if(!item) return; //or display an alert
//item already exists
if($scope.sports.indexOf(item) > -1) return; //or display a different alert
$scope.sports.push(item);
$scope.newItem = null;
}
Hey guys my search filters are not working for some reason. You can check in this website! Like i dont understand why its wrong. I followed the tutorial exactly from this site. Please help!
Here is my code:
index.html:
<!DOCTYPE html>
<html lang= "en">
<head>
<meta charset="UTF-8" />
<title>Basic Login Form</title>
<script data-require="angular.js#1.4.x" src="https://code.angularjs.org/1.4.8/angular.js" data-semver="1.4.8"></script>
<script src = "https://rawgit.com/nirus/Angular-Route-Injector/master/dist/routeInjector.js"></script>
<script src = "https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular-route.js"></script>
<script type="text/javascript" src="main.js"></script>
</head>
<body ng-app = "app">
<div ng-controller = "people">
<ul>
<h2>Names And Ages of Programmers:</h2>
<li ng-repeat = "person in persons | filter: searchBox">
Name: {{person.Name}}<br>
Age: {{person.Age}}<br>
Favorite-Color : {{person.Fav_Color}}
</li>
</ul>
</div>
<div id = "searchBoxes">
Global Search Filter : " <input type="text" ng-model="globalSearch.$"><br>
Name Search Filter: <input type="text" ng-model = "globalSearch.Name"><br>
Age Search Filter: <input type="text" ng-model = "globalSearch.Age"><br>
Favorite Color Search Filter: <input type="text" ng-model = "globalSearch.Fav_Color"><br>
</div>
</div>
</body>
</html>
main.js:
var filex = {
"records" : [
{
"Name":"Something",
"Age":"18",
"Fav_Color" : "Orange"
},
{
"Name": "Anonymus",
"Age" : "???",
"Fav_Color" : "Blue"
}
]
}
var app = angular.module('app',[])
app.controller('people', function($scope){
$scope.persons = filex.records
})
You missed the input to which your filter is bound:
<input type="text" ng-model="searchBox">
Adding this is vital since the ng-model="searchBox" here is bound to your search results: <li ng-repeat = "person in persons | filter: searchBox"> here.
Your search results are filtered based on model searchBox.
JsBin example
I have an AngularJS app that I manually bootstrap at time 't'. At time 't + 1', I would like to show an HTML element that has no ng-controller attached. I would like to dynamically add a ng-controller to this element so it can communicate with my javascript code.
How can I do that?
PS I tried to dynamically add the ng-controller attribute to the element but it doesn't work.
To do that you need to compile elements.
HTML
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.5/angular.min.js"></script>
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<link href="main.css" rel="stylesheet" type="text/css" />
<script src="main.js"></script>
<meta charset=utf-8 />
<title>Angular JS</title>
</head>
<body ng-controller="parentCtrl">
<button ng-click="setCtrl2()">Set Controller</button>
<div id="placeholder">
<span></span>
<select>
<option></option>
</select>
<span class="input-append">
<input id="add" type="text" placeholder="Another one ?" ng-model="addName" />
<input type="submit" class="btn btn-primary" ng-click="addRow()" value="+ add" />
</span>
</div>
</body>
</html>
Javascript
angular.module('app', []);
angular.module('app').controller('ctrl', function($scope) {
$scope.rows = ['Paul','John','Lucie'];
$scope.name = 'Jack';
$scope.addRow = function(){
$scope.rows.push($scope.addName);
$scope.addName = "";
console.log($scope.rows);
};
})
.controller('parentCtrl', function($scope) {
$scope.setCtrl2 = setCtrl;
});
function setCtrl() {
var elem = document.getElementById('placeholder');
elem.setAttribute('ng-controller', 'ctrl');
var eSpan = elem.children[0];
var eSelect = elem.children[1].children[0];
eSpan.setAttribute('ng-bind', 'name');
eSelect.setAttribute('ng-repeat', 'row in rows');
eSelect.setAttribute('value', '{{ row }}');
eSelect.setAttribute('ng-bind', 'row');
var injector = angular.element(elem).injector();
var compile = injector.get('$compile');
var rootScope = injector.get('$rootScope');
var result = compile(elem)(rootScope);
// When outside of AngularJS you need to call digest
// rootScope.$digest();
}
See: http://codepen.io/skarllot/pen/LVKpgd
You don't mention whether you've looked at previously asked questions. I found two which look like they could address the question you've asked:
Loading an AngularJS controller dynamically
How to bind an AngularJS controller to dynamically added HTML?
I want to hide "add new button" when Im creating the record. and only show it back when Im done creating record.
Same as the "submit one button", I want to hide it (submit one button) and showing back the "add new button" as Im done submitting. How to do that?
below is my code and here is my plunkr:
index.html
<!DOCTYPE html>
<html ng-app="angularjs-starter">
<head lang="en">
<meta charset="utf-8">
<title>Custom Plunker</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.3/angular.min.js"></script>
<link rel="stylesheet" href="style.css">
<script>
document.write('<base href="' + document.location + '" />');
</script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<a ng-show="hideAddButton" ng-hide="hideAddButton" ng-click="addNew();hideAddButton = !hideAddButton">+ add new</a>
<form name="mainForm" ng-submit="submitAll()">
<ul>
<li ng-repeat="item in items" ng-form="subForm">
<input type="text" required name="name" ng-model="item.name"/>
<span ng-show="subForm.name.$error.required">required</span>
<button type="button" ng-disabled="subForm.$invalid" ng-click="submitOne(item);hideAddButton = !hideAddButton">Submit One</button>
</li>
</ul>
<button type="submit" ng-disabled="mainForm.$invalid">Submit All</button>
</form>
<hr/>
<div ng-show="lastSubmit">Last Submit:</div>
<pre>{{lastSubmit | json}}</pre>
</body>
</html>
app.js
var app = angular.module('angularjs-starter', []);
app.controller('MainCtrl', function($scope) {
$scope.items = [];
$scope.addNew = function (){
$scope.items.push({ name: '' });
};
$scope.submitOne = function (item){
$scope.lastSubmit = angular.copy(item);
};
$scope.submitAll = function() {
$scope.lastSubmit = angular.copy($scope.items);
}
});
Here is my solution: http://plnkr.co/edit/8kOmWQ96UFkNOxZqcFMS?p=preview
app.controller('MainCtrl', function($scope) {
$scope.items = [];
$scope.isSubmitting = false;
$scope.addNew = function (){
$scope.isSubmitting = true;
// Here I added a state for each item.
$scope.items.push({ name: '', showButton:true });
};
$scope.submitOne = function (item){
item.showButton = false;
$scope.isSubmitting = false;
$scope.lastSubmit = angular.copy(item);
};
$scope.submitAll = function() {
$scope.items.forEach(function(i){i.showButton=false;})
$scope.isSubmitting = false;
$scope.lastSubmit = angular.copy($scope.items);
}
});
HTML
<body ng-controller="MainCtrl">
<a ng-hide="isSubmitting" ng-click="addNew();">+ add new</a>
<form name="mainForm" ng-submit="submitAll()">
<ul>
<li ng-repeat="item in items" ng-form="subForm">
<input type="text" required name="name" ng-model="item.name"/>
<span ng-show="subForm.name.$error.required">required</span>
<button ng-show="item.showButton" type="button" ng-disabled="subForm.$invalid" ng-click="submitOne(item);">Submit One</button>
</li>
</ul>
<button type="submit" ng-disabled="mainForm.$invalid">Submit All</button>
</form>
<hr/>
<div ng-show="lastSubmit">Last Submit:</div>
<pre>{{lastSubmit | json}}</pre>
</body>
I think this is what you are asking for, but I don't think the "submit all" button makes much sense in this scenario, unless you allow to add more items before submitting them (but you clearly state you want the "add new"-button hidden).
Also I was unsure if you actually wanted to store a state for each item, but showing/hiding all buttons didn't make much sense to me either...
You should use the ng-show or ng-hide directives.
with ng-show:
<button ng-show="hideAddButton === false">
with ng-hide:
<button ng-hide="hideAddButton === true">