Scope values aren't displayed when getting HTML from server - javascript

UPDATE
After doing many tests on my code I'm updating my previous question, as it's now clearer to me what's not working.
My HTML file is served when I browse to the / directory in my local
All the pages loads nicely except for the content of the $scope in my directives (see below).
I've tested loading the page directly (just clicked on the html file) and I can see the content.
I'm not sure where the problem is.
I've removed all un-necessary lines from the HTML file to give a better pictures of my code. the {{}} is just the templating engine language.
HTML
<DOCTYPE html>
<html ng-app="docsSimpleDirective">
<head>
<link rel="stylesheet" type="text/css" href="/css/text.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0- alpha.5/css/bootstrap.min.css" integrity="sha384- AysaV+vQoT3kOAXZkl02PThvDr8HYKPZhNT5h/CXfBThSRXQ6jW5DO2ekP5ViFdi" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.1.1.js" integrity="sha256-16cdPddA6VdVInumRGo6IbivbERE8p7CQR3HzTBuELA=" crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script src="https://www.atlasestateagents.co.uk/javascript/tether.min.js"> </script><!-- Tether for Bootstrap -->
<script src="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/js/bootstrap.min.js"></script><!-- Bootstrap -->
</head>
<body >
<h3>Select some text </h3>
<div ng-controller="Controller">
{% for i in result %}
<div id={{i._id}} class="task" commentId = {{i._id}} get-popover- content>{{i.text}} </div>
<div id={{i._id}} class="task" commentId = {{i._id}} my-customer="customer">{{i.text}} </div>
<br/>
{% endfor %}
</div>
<script>
(function(angular) {
'use strict';
angular.module('docsSimpleDirective', [])
.controller('Controller', ['$scope', function($scope) {
$scope.customer = {
name: 'Naomi',
address: '1600 Amphitheatre'
};
}])
.directive('myCustomer', function() {
return {
scope: {
myCustomer: '='
},
template: 'Name: {{myCustomer.name}} Address: {{myCustomer.address}}'
};
});
})(window.angular);
</script>
</body>
</html>

You can create an isolated scope to the directive as below with the same name as a directive name,
scope: {
myCustomer: '='
}
and link the controller's $scope.customer to this isolated scope as below,
<div ... my-customer="customer"></div>
And change your template to access the same like this,
template: 'Name: {{myCustomer.name}} Address: {{myCustomer.address}}'
Working sample:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body>
<h3>Select some text </h3>
<div ng-controller="Controller">
<div id="test1" class="task" commentId="test1" get-popover-content>{{i.text}} </div>
<div id="test2" class="task" commentId="test2" my-customer="customer">{{i.text}} </div>
<br/>
</div>
<script>
(function(angular) {
'use strict';
angular.module('docsSimpleDirective', [])
.controller('Controller', ['$scope', function($scope) {
$scope.customer = {
name: 'Naomi',
address: '1600 Amphitheatre'
};
}])
.directive('myCustomer', function() {
return {
scope: {
myCustomer: '='
},
template: 'Name: {{myCustomer.name}} Address: {{myCustomer.address}}'
};
});
angular.bootstrap(document, ['docsSimpleDirective']);
})(window.angular);
</script>
</body>

You have to use scope: { .... } inside directive to access your controller scope
Controller
(function(angular) {
'use strict';
angular.module('docsSimpleDirective', [])
.controller('Controller', ['$scope', function($scope) {
$scope.customer = {
name: 'Naomi',
address: '1600 Amphitheatre'
};
}])
HTML
// use this directive and pass customer to the directive scope
<my-customer customer="customer"></my-customer>
Directive
.directive('myCustomer', function() {
return {
scope: {
customer: '=customer'
}
template: 'Name: {{customer.name}} Address: {{customer.address}}'
};
});

Surround with
{{% raw %}} ... {{% endraw %}}

This is probably a better pattern for what you're trying to achieve (note the comment for an API call for your customers in JSON format).
Calling for the data via API after the page has loaded will allow you to keep your HTML/CSS/JAVASCRIPT as totally static files (no templating engine etc) and decoupled from your data.
It will load faster and give you the option to host your web front-end entirely on something like a CDN (which frees up your API server to focus only on requests for data/ sessions stuff like that).
<DOCTYPE html>
<html ng-app="docsSimpleDirective">
<head>
<!-- <link rel="stylesheet" type="text/css" href="/css/text.css"> -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css" integrity="sha384-AysaV+vQoT3kOAXZkl02PThvDr8HYKPZhNT5h/CXfBThSRXQ6jW5DO2ekP5ViFdi" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.1.1.js" integrity="sha256-16cdPddA6VdVInumRGo6IbivbERE8p7CQR3HzTBuELA=" crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script src="https://www.atlasestateagents.co.uk/javascript/tether.min.js"> </script><!-- Tether for Bootstrap -->
<script src="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/js/bootstrap.min.js"></script><!-- Bootstrap -->
</head>
<body>
<h3>Select some text</h3>
<div ng-controller="Controller">
<div ng-repeat="customer in customers">
<!-- not sure what 'id' or 'text' values are, you should pass them in
via API if they are needed -->
<div id={{i._id}} class="task" commentId = {{i._id}} get-popover- content>{{i.text}} </div>
<div id={{i._id}} class="task" commentId = {{i._id}} my-customer="customer">{{i.text}} </div>
<br/>
</div >
</div>
<script>
(function(angular) {
'use strict';
angular.module('docsSimpleDirective', [])
.controller('Controller', ['$scope', function($scope) {
// make a request to api to get customers in JSON format
// assign result to scope.customers
$scope.customers= [
{
name: 'Naomi',
address: '1600 Amphitheatre'
},
{
name: 'Amir',
address: '58 W 54th st'
}
];
}])
.directive('myCustomer', function() {
return {
scope: {
myCustomer: '='
},
template: 'Name: {{myCustomer.name}} Address: {{myCustomer.address}}'
};
}); // directive
})(window.angular);
</script>
</body>
</html>
you can also mock a REST API server by making a request to a static file like this:
$http.get("./myFakeAPI.json").then(function(response){
$scope.customers = response.data.customers;
});
where the contents of the file 'myFakeAPI.json' is:
{
"customers":
[
{
name: 'Naomi',
address: '1600 Amphitheatre'
},
{
name: 'Amir',
address: '58 W 54th st'
}
]
}

Related

The controller does not get bind to the view

I just started learning AngularJS and facing a problem. When I run the follwing code {{ cust.name }} - {{ cust.city }} gets printed instead of the actual data that I pass.
My code:
<html data-ng-app="">
<head>
<title>Using angularJS directive and data binding </title>
</head>
<body>
<div data-ng-controller="SimpleController">
Name:
<br/>
<input type="text" data-ng-model="name" />
<br/>
<ul>
<li data-ng-repeat="cust in customers | filter:name"> {{ cust.name }} - {{ cust.city }}
</li>
</ul>
</div>
<script src="Scripts/angular.min.js"></script>
<script>
function SimpleController($scope) {
$scope.customers = [{
name: 'Abhijeet Singh',
city: 'New Delhi'
}, {
name: 'Dhiraj Mehta , city: New Delhi '
}];
}
</script>
</body>
</html>
A few things are missing from your code.
First it is good practice to name your app and a controller:
<body data-ng-app='myApp' data-ng-controller='myCtrl'>
Second whenever you refer to anything in Angular is has to be in scope of the controller. Currently your $scope is in scope of the "SimpleController" function and not of Angular's controller (you need an angular controller to have $scope available both within the controller and within your html e.g. the double curly brackets):
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
//$scope is available anywhere within this scope
}
Here is an example of your code working: https://jsfiddle.net/AKMorris/03hshn5m/
You will need to declare the app name and see the other settings.
Rest of the things are same.
var myApp = angular.module("MyApp", []);
var simpleController = angular.module("SimpleController", SimpleController);
simpleController.$inject = ['$scope'];
function SimpleController($scope){
$scope.customers = [{
name: 'Abhijeet Singh',
city: 'New Delhi'
}, {
name: 'Dhiraj Mehta , city: New Delhi '
}];
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<html data-ng-app="MyApp">
<head>
<title>Using angularJS directive and data binding </title>
</head>
<body>
<div data-ng-controller="SimpleController">
Name:
<br/>
<input type="text" data-ng-model="name" />
<br/>
<ul>
<li data-ng-repeat="cust in customers | filter:name"> {{cust.name }}-{{cust.city}}
</li>
</ul>
</div>
</body>
</html>

Angularjs and ui-grid - add event keypress in cell

First of all, I want to say that I am beginner with angularjs :D
My problem is:
I'm trying add the keypress event when user goes to edit the value in cell on angular ui-grid.
In the beginning it seems to work, but when I finish editing a cell and mute the focus the value disappears.
Here is the link to see the event running: https://plnkr.co/edit/vw8W6PqFt11nt4BDhWu9
And here is my code:
File: index.html
<!doctype html>
<html ng-app="app">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.js"></script>
<script src="//cdn.rawgit.com/angular-ui/bower-ui-grid/v3.0.6/ui-grid.min.js"></script>
<link rel="stylesheet" href="//cdn.rawgit.com/angular-ui/bower-ui-grid/v3.0.6/ui-grid.min.css" type="text/css" />
<link rel="stylesheet" href="main.css" type="text/css">
</head>
<body>
<div ng-controller="MainCtrl">
<div id="grid1" ui-grid="gridOptions" ui-grid-edit class="grid"></div>
</div>
<script src="app.js"></script>
</body>
</html>
File: app.js
(function() {
var app = angular.module('app', ['ui.grid', 'ui.grid.edit']);
app.controller('MainCtrl', ['$scope', '$http', function($scope, $http) {
$scope.gridOptions = {
columnDefs: [{
field: 'name'
}, {
field: 'amount',
name: 'Number'
}, {
field: 'someValue',
name: 'SomeValue',
editableCellTemplate: 'template-cell.html'
}]
};
$http.get('data.json')
.success(function(data) {
$scope.gridOptions.data = data;
});
}]);
app.directive('numbersOnly', function () {
return {
require: 'ngModel',
link: function (scope, element, attr, ngModelCtrl) {
function fromUser(text) {
if (text) {
var transformedInput = text.replace(/[^0-9]/, '');
if (transformedInput !== text) {
ngModelCtrl.$setViewValue(transformedInput);
ngModelCtrl.$render();
}
return transformedInput;
}
return undefined;
}
ngModelCtrl.$parsers.push(fromUser);
}
};
});
}());
File: cell-template.html
<div>
<form name="inputForm">
<input type="text"
ui-grid-editor
ng-model="someValue"
data="row.entity.someValue"
ng-class="'colt' + col.uid"
numbers-only />
</form>
</div>
I need this functionality with keypress event only. How do I update the model with the input field value ?
Thanks.
The problem is that your column value is not correctly bound to the ngModel in the cell template.
The correct value would be to use the MODEL_COL_FIELD which you can read more about in the wiki, look at section "Editable Cell Templates"
Update your cell-template.html to
<div>
<form name="inputForm">
<input type="text"
ui-grid-editor
ng-model="MODEL_COL_FIELD"
ng-class="'colt' + col.uid"
numbers-only />
</form>
</div>

Simpledirective not injecting.

Hey I was wondering could someone help me and tell me why my directives aren't running in Webstorm 9.0. Why is it not adding in my directive? I thought this would be very straight forward but it doesn't seem to be injecting it.
enter code here http://plnkr.co/edit/fKKS1TINMHT4yJF4c9Ol?p=preview
Here is a plunker
To star off you havent defined your name in the ng-app thats why your app was not working
and the script files were in different order.
http://plnkr.co/edit/2SthQC5fADsi1rdEhq3C?p=preview
var app = angular.module('docsSimpleDirective', []);
app.controller('Controller', function($scope) {
console.log('Hi');
$scope.customer = {
name: 'Naomi',
address: '1600 Amphitheatre'
};
})
.directive('myCustomer', function() {
return {
template: 'Name: {{customer.name}} Address: {{customer.address}}'
};
});
Your html
<!DOCTYPE html>
<html ng-app="docsSimpleDirective">
<head>
<link rel="stylesheet" href="style.css">
<script src = "https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<h1>Hello Plunker!</h1>
<div ng-controller="Controller">
<div my-customer/>
</div>
</body>
</html>
Hope it helps
Please change angular.module('docsSimpleDirective', ['index.html']) to angular.module('docsSimpleDirective', []) . index.html is not a dependency. We are linking the js file to html file. not the other way round.
Also, please change <html ng-app> to <html ng-app='docsSimpleDirective'> Because we have given the module name as docsSimpleDirective in angular.module('docsSimpleDirective', [])

AngularJS Controller not working in nested Controller

Got a questions regarding the select option value, i can get the value as the select options changed, but i am not able to get the value of the select options thru the search button, it will just give a value undefined. So where is the problem?
index.html
<div ng-controller="MatIncListCtrl">
<button class="fluid labeled icon blue ui button top attached"><i class="ellipsis vertical icon"></i>Toggle Filters Pane</button>
<div class="ui attached segment" uib-collapse="isCollapsed">
<form role="form" class="ui form">
<div class="fields">
<div class="twelve wide field" ng-controller="DistinctSupplierCtrl">
<label>Supplier</label>
<select ng-model="Supplier" class="ui fluid dropdown" ng-options="x.supp_no as x.supp for x in data" ng-change="selectAction()">
<option></option>
</select>
</div>
</div>
</form>
<br />
<button type="button" class="ui orange fluid labeled icon button" tabindex="0" ng-click="FindMatInc()"><i class="search icon"></i>Search</button>
</div>
</div>
controller.js
.controller('DistinctSupplierCtrl', function($scope, $http) {
$scope.selectAction = function() {
console.log($scope.Supplier);
};
var xhr = $http({
method: 'post',
url: 'http://localhost/api/list-distinct-supp.php'
});
xhr.success(function(data){
$scope.data = data.data;
});
})
.controller('MatIncListCtrl', function ($scope, $http) {
$scope.FindMatInc = function (){
console.log($scope.Supplier);
}
});
If you want to access a value from a scope, you've got to make sure it's in that scope or in the scope of it's ancestors. Now your ng-model is declared in the child scope. If you want to access it from the parent scope, you'll need to declare it in the parent scope. That way when the model get changed, it changed in the parent scope and thus accessible in both scopes:
Working example:
angular.module('App', []);
angular.module('App').controller('ControllerParent', [
'$scope',
function ($scope) {
// Model value declared in parent scope
$scope.selected = {};
}
]);
angular.module('App').controller('ControllerChild', [
'$scope',
function ($scope) {
$scope.options = [{
id: 1,
name: 'Alpha'
}, {
id: 2,
name: 'Bravo'
}, {
id: 3,
name: 'Charlie'
}, {
id: 4,
name: 'Delta'
}];
}
]);
<!DOCTYPE html>
<html ng-app="App">
<head>
<script type="application/javascript" src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.js"></script>
</head>
<body ng-controller="ControllerParent">
<div ng-controller="ControllerChild">
<select ng-model="selected.value" ng-options="option.name for option in options"></select>
ControllerSub: {{selected}}
</div>
ControllerMain: {{selected}}
</body>
</html>
Failing example:
angular.module('App', []);
angular.module('App').controller('ControllerParent', [
'$scope',
function ($scope) {}
]);
angular.module('App').controller('ControllerChild', [
'$scope',
function ($scope) {
// Model value declared in child scope
$scope.selected = {};
$scope.options = [{
id: 1,
name: 'Alpha'
}, {
id: 2,
name: 'Bravo'
}, {
id: 3,
name: 'Charlie'
}, {
id: 4,
name: 'Delta'
}];
}
]);
<!DOCTYPE html>
<html ng-app="App">
<head>
<script type="application/javascript" src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.js"></script>
</head>
<body ng-controller="ControllerParent">
<div ng-controller="ControllerChild">
<select ng-model="selected.value" ng-options="option.name for option in options"></select>
ControllerSub: {{selected}}
</div>
ControllerMain: {{selected}}
</body>
</html>
Descendant scopes have access to the values of their ancestors. Ancestors don't have access to values of their descendants.
Another way to work on nested controllers using the controller as syntax.
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>AngularJS Tutorial</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.min.js"></script>
<script>
angular.module('app', []);
angular.module('app').controller("MainController", function(){
var vm = this; //The vm in this case means viewmodel
vm.title = 'AngularJS Nested Controller Example';
});
angular.module('app').controller("SubController", function(){
var vm = this;
vm.title = 'Sub-heading';
});
</script>
</head>
<body ng-app='app' ng-controller='MainController as main'>
<div class='container'>
<h1>{{main.title}}</h1>
<div ng-controller='SubController as sub'>
<h2>{{sub.title}}</h2>
<p>If we were not using the <strong>ControllerAs</strong> syntax we would have a problem using title twice!</p>
</div>
</div>
</body>
</html>

console.log for $scope in angular js

Why I'm not able to console output $scope values ? I'm trying to extract user assigned values from the pages and retrieve in controller. Eventually i would like to pass this to service so multiple controllers can access these data.
HTML
<!DOCTYPE html>
<html lang="en-us" ng-app="myApp">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta charset="UTF-8">
<link rel="stylesheet" href="css/bootstrap.min.css" />
<!-- CDN lib files -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular-animate.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.1.0/ui-bootstrap-tpls.min.js"></script>
<!-- custom angular script -->
<script src="js/app.js"></script>
</head>
<body>
<div class="container">
<div ng-controller="mainController">
<h1>Hello world!</h1>
<label> Please enter something</label>
<input textarea ng-model="name"></input>
<h4> This is what you entered : {{ name }} </h4>
<h4 style=color:red> now filtering: {{ lower() }}</h4>
</div>
</div>
</body>
</html>
APP.JS
var myApp = angular.module('myApp', []);
myApp.controller('mainController', ['$scope', '$filter', function($scope, $filter) {
$scope.name = 'Test ';
$scope.lower = function(){
return $filter('lowercase')($scope.name);
}
$scope.name = $scope.lower();
console.log($scope.name);
console.log($scope.lower());
}]);
Console will output values upon initializing but not after user make changes.
You need to watch the scope variable:
$scope.$watch('name', function() {
console.log($scope.name);
});
More information: https://stackoverflow.com/a/15113029/5787736
Just a more "functional" version. Everyone is right, you are logging the observable, not what was observed. What you want is for console.log to be called on each change to $scope, not called once (as you have it now).
$scope.$watch("name", console.log);
You're logging only from the constructor. If you want to log each time something changes, consider a watch:
$scope.$watch("name", function() {
console.log($scope.name);
}
Why would you expect a controller to be rerendered when a scope variable changes? You can use scope watchers or input event listeners to listen for changes.
Here's an example with a watcher:
var myApp = angular.module('myApp', []);
myApp.controller('mainController', ['$scope', '$filter', function($scope, $filter) {
$scope.name = 'Test ';
$scope.lower = function(){
return $filter('lowercase')($scope.name);
}
$scope.name = $scope.lower();
console.log($scope.name);
console.log($scope.lower());
$scope.$watch('name', function() {
console.log($scope.name);
console.log($scope.lower());
});
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" class="container">
<div ng-controller="mainController">
<h1>Hello world!</h1>
<label>Please enter something</label>
<input textarea ng-model="name" />
<h4> This is what you entered : {{ name }} </h4>
<h4 style=color:red> now filtering: {{ lower() }}</h4>
</div>
</div>

Categories

Resources