Array Not Propagating to View - angularjs

I'm very new to Angularjs and Firebase and have been stuck on this for quite some time. I'm trying to use ng-repeat to iterate over an array of procedures I set in my controller. I can print $scope.procedures in my controller but not in index.html. Any idea where I'm going wrong?
index.html
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="utf-8">
<!-- Angular JS -->
<script src="lib/angular/angular.min.js"></script>
<!-- Firebase -->
<script src="https://cdn.firebase.com/js/client/2.2.4/firebase.js"></script>
<script src="js/controllers.js"></script>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="container-fluid" id="logo">
</div>
<div class="container" ng-controller="MainCtrl">
<div class="col-sm-7 col-md-6 col-md-offset-1" id="message">
<label id="input-label">Insurance Company</label>
<input ng-model="insurQuery" class="form-control insurInput" id="input-box" placeholder="Patient Insurance Company" autofocus>
<div ng-if="showProcedures()">
<h3>Procedures Covered by <span id="proc-span">{{selectedInsur.name}}</span></h3>
<ul class="list-group">
<li class="list-group-item" ng-repeat="proc in procedures">
<a>{{ proc.name }}</a>
</li>
</ul>
</div>
</div>
<div class="col-sm-4 col-md-4 col-md-offset-1" id="message2">
<ul class="list-group">
<li class="list-group-item ng-class: {'active':isSelectedInsur(company)}" ng-repeat="company in insuranceCompanies | filter: insurQuery | orderBy: 'name'">
{{ company.name }}
</li>
</ul>
</div>
</div>
</body>
</html>
controllers.js
var myApp = angular.module('myApp', ['ui.bootstrap', 'firebase']);
myApp.controller("MainCtrl", function($scope, $firebaseArray) {
var ref = new Firebase("https://payoralerts.firebaseio.com/companies");
// download the data into a local object
$scope.insuranceCompanies = $firebaseArray(ref);
$scope.selectedInsur = null;
$scope.isSelected = false;
$scope.procedures = [];
function getProcedures() {
var companiesBaseUrl = "https://payoralerts.firebaseio.com/companies/"
var proceduresBaseRef = new Firebase("https://payoralerts.firebaseio.com/procedures/");
var companyUrl = companiesBaseUrl + $scope.selectedInsur.$id + "/procedures/";
var proceduresUrl = "https://payoralerts.firebaseio.com/procedures/"
var companyProceduresRef = new Firebase(companyUrl);
companyProceduresRef.on("child_added", function(snap) {
proceduresBaseRef.child(snap.key()).once("value", function(data) {
if (data.val()) {
console.log("Name: ", data.val().name);
$scope.procedures.push(data.val());
console.log("scope procedures: ", $scope.procedures);
};
});
});
}
function setSelectedInsur(company) {
if ($scope.selectedInsur == company) {
$scope.selectedInsur = null;
$scope.isSelected = null;
} else {
$scope.selectedInsur = company;
$scope.isSelected = true;
getProcedures();
console.log("scope procedures: ", $scope.procedures);
}
}
function isSelectedInsur(company) {
return $scope.selectedInsur !== null && company.name == $scope.selectedInsur.name;
}
function showProcedures() {
if ($scope.isSelected == true) {
return true;
} else {
return false;
}
}
$scope.setSelectedInsur = setSelectedInsur;
$scope.isSelectedInsur = isSelectedInsur;
$scope.showProcedures = showProcedures;
// $scope.procedures = $scope.procedures;
});

I'm also pretty new to Angular as well and one of the most deep and hard topics in angular (imo) is how angular binding works under the hood.
In your case calling $scope.$apply() works but keep in mind that this is not the best solution and you should not start calling it whenever you have a binding problem.
I really encourage you to take some time reading some articles about what angular binding really is. You can start here and here. After this get back to your code to understand what you are doing wrong. :)

Related

How do I send a div value to a function in angular controller

<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<script>
var app = angular.module("myShoppingList", []);
app.controller("myCtrl", function($scope) {
$scope.products = ["Milk", "Bread", "Cheese"];
$scope.addItem = function () {
$scope.errortext = "";
if (!$scope.addMe) {return;}
if ($scope.products.indexOf($scope.addMe) == -1) {
$scope.products.push($scope.addMe);
} else {
$scope.errortext = "The item is already in your shopping list.";
}
}
$scope.removeItem = function (x) {
$scope.errortext = "";
$scope.products.splice(x, 1);
}
});
</script>
<div ng-app="myShoppingList" ng-controller="myCtrl">
<ul>
<li ng-repeat="x in products">{{x}}<span ng-click="removeItem($index)">×</span></li>
</ul>
<input ng-model="addMe">
<button ng-click="addItem()">Add</button>
<p>{{errortext}}</p>
</div>
</body>
</html>
The line <input ng-model="addMe"> takes the input values and adds to the list
What if I want to define a <div> instead of <input> to send the value to my controller instead of <input> ? I have been trying this for long now and can not get a value enclosed between <div> and </div> sent over to the controller.
Just put your x as parameter on addToCart to add it to cart in the controller.
See demo here.

AngularJS multiple checkboxes doubts (Angular Material)

I'm trying to get multiple Angular Material checkboxes with the same ng-model. I have two problems: how to get default checked checkboxes, and how to make at least one of these checkboxes to be required. I tried with ng-checked, but then I can't POST the values through the form.
HTML
<label for="inputPassword3" class="col-sm-2 control-label">Školski sat *</label>
<div class="col-sm-10" >
<span class="col-sm-2" ng-repeat="period in periods">
<md-checkbox ng-model="form.periods[period]" ng-click="toggle(period, selected)">
{{ period }}. sat
</md-checkbox>
</span>{{selected | json}}
</div>
App.js
$scope.periods = [1,2,3,4,5,6,7,8,9,0]; /*broj sati*/
$scope.selected = [2];
$scope.toggle = function (period, list) {
var idx = list.indexOf(period);
if (idx > -1) {
list.splice(idx, 1);
}
else {
list.push(period);
}
};
$scope.exists = function (period, list) {
return list.indexOf(period) > -1;
};
Please, help.
Actually your ngModel is an object, so to get selected value rendered on load, you should do the following:
$scope.model = {};
$scope.model.periods = {"2": true};
And to get all selected checkboxes you should iterate over the keys, as below:
$scope.save = function() {
// Get all checked boxes
var checked = Object.keys($scope.model.periods).filter(function(key) {
return $scope.model.periods[key];
});
console.log(checked);
}
See it working:
(function() {
angular
.module('app', ['ngMaterial'])
.controller('MainCtrl', MainCtrl);
MainCtrl.$inject = ['$scope'];
function MainCtrl($scope) {
$scope.model = {};
$scope.model.periods = {"2": true};
$scope.periods = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; /*broj sati*/
$scope.save = function() {
// Get all checked boxes
var checked = Object.keys($scope.model.periods).filter(function(key) {
return $scope.model.periods[key];
});
console.log(checked);
}
}
})();
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular-aria.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular-animate.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-material/1.0.9/angular-material.min.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular-material/1.0.9/angular-material.min.js"></script>
</head>
<body ng-controller="MainCtrl">
<form name="form">
<div class="col-md-12">
<label for="inputPassword3" class="col-sm-2 control-label">Školski sat *</label>
<div class="col-sm-10">
<span class="col-sm-2" ng-repeat="period in periods">
<md-checkbox ng-model="model.periods[period]">
{{ period }}. sat
</md-checkbox>
</span>
</div>
<span ng-bind="model.periods | json"></span>
<hr>
<button type="button" class="btn btn-success" ng-click="save()">Save data</button>
</div>
</form>
</body>
</html>
I hope it helps.

Github API is not returning values for a user

JS Fiddle: https://jsfiddle.net/o1fb31z6/3/
Okay, so I am doing a brief little project for an organization.
But here's the problem I get: whenever I query this user using the Search portion of the Github API, it returns nothing. I know the code works because if I adjust usernames, it returns values. Anyone ever have this problem?
My work around query above also gets them to return values, but some of the information is off (Fork Count).
app.html:
<!doctype html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html">
<title>Github API Webapp using AngularJS</title>
</head>
<body ng-app="app">
<div data-ng-controller='GitHubCtrl' data-ng-init='getGitInfo()'>
<h1>Simple Github API Webapp</h1>
<p>Search for a particular repo</p>
<input type="text" ng-model="repoName" placeholder="Github repo name...">
Find Repos
<div ng-show='repoSearched'>
<p><strong>Repos found by search:</strong></p>
<ul ng-repeat='result in results'>
<li> {{result.name}} </li>
<li>User:{{result.owner.login}}</li>
</ul>
</div>
<div>
<h2>User: {{user.name}}
<span class="smallname"> {{user.login}} </span>
</h2>
</div>
<div>
<a href="{{ user.html_url }}" target="_blank">
<img src="{{ user.avatar_url }}" width="80" height="80" alt="{{ user.login }}"></a>
</div>
<div ng-show="reposFound">
<p><strong>Repos List:</strong></p>
<ul ng-repeat="repo in repos">
<li> {{repo.name}} </li>
<li>Forks Count: {{repo.forks_count}}</li>
<li>Created at:{{repo.created_at}}</li>
<li>Language: {{repo.language}}</li>
</ul>
</div>
</div> <!-- End of controller div -->
<script src='app.js'></script>
</body>
</html>
app.js:
angular.module('app',[]).controller('GitHubCtrl', GitHubCtrl);
function GitHubCtrl($scope, $http) {
// Set the default user here
$scope.username = 'aipub';
// getGitInfo queries the Github api for user information and public repositories
$scope.getGitInfo = function () {
// This API call searches for logo of our user.
$http.get("https://api.github.com/users/" + $scope.username).success(function (data) {
$scope.user = data;
});
// This API call searches for the repos of the user
$http.get("https://api.github.com/users/" + $scope.username + "/repos").success(function (data) {
nameFormatter(data);
$scope.repos = data;
$scope.reposFound = data.length > 0;
});
}
// comment about function below
$scope.searchGitRepos = function () {
$http.get("https://api.github.com/search/repositories?q=" + $scope.repoName + "+in:name+user:" + $scope.username).success(function (data) {
$scope.results = data.items;
$scope.repoSearched = data.items.length > 0;
});
}
}
// *args: array of objects of any length greater than 0. Capitalizes the name string of the each object
// in the array by splitting the words into their individual components, excluding if the words are
// 'python' or 'mongo'.
function nameFormatter(data) {
for (var i=0; i < data.length; i++) {
var formatName = data[i].name.split('-');
for (var j=0; j < formatName.length; j++) {
if (!(formatName[j] === 'python' || formatName[j] === 'mongo')) {
formatName[j] = formatName[j].charAt(0).toUpperCase() + formatName[j].substr(1);
}
}
data[i].name = formatName.join(' ');
}
}
// $http.get("https://api.github.com/search/repositories?q=user:tulun").success(function (data) {
// console.log(data);
// });
// https://api.github.com/search/repositories?q=user:tulun
// https://api.github.com/search/repositories?q=user:aipub
You need to setup the access token
you can try this project: https://github.com/JohnnyTheTank/angular-github-api-factory.

Count items with value in angularjs scope per row

I have a site that uses angular ng-repeat to show data from my scope and all works fine, but I need to count items to show a percentage complete, but can't seem to find a solution online. I am still very new to Angular and JS, so apologies if its an easy solution.
The below is a simplified and generalized example of what I am looking to achieve:
$scope.devices = [
{Detail_A:'ShowA1',Detail_B:'ShowB1',Status_A:'',Status_B:'OK',Status_C:'',Status_D:'OK',ENG_A:'OK',ENG_B:'OK',ENG_C:'OK'},
{Detail_A:'ShowA2',Detail_B:'ShowB2',Status_A:'OK',Status_B:'OK',Status_C:'OK',Status_D:'OK',ENG_A:'',ENG_B:'',ENG_C:''},
{Detail_A:'ShowA3',Detail_B:'ShowB3',Status_A:'OK',Status_B:'OK',Status_C:'OK',Status_D:'OK',ENG_A:'OK',ENG_B:'OK',ENG_C:'OK'}
]
I would like to show a percentage of items that state 'OK' within the two pre-fixed items: Status_* and ENG_*. This can be either by having to loop each one or better to be able to use the prefix to calculate over a group.
<div ng-repeat="device in devices">
<div class="col-md-2">{{StatusPercentComplete}}</div>
<div class="col-md-1">{{ENGPercentComplete}}</div>
<div class="col-md-1">{{device.Detail_A}}</div>
<div class="col-md-1">{{device.Detail_B}}</div>
</div>
So for row 1, StatusPercentComplete would be 50% and ENGPercentComplete would be 100%.
Any direction would be much appreciated.
I just put together a little proof of concept with a refactored percent calculation function, so that you can reuse it for either Status_x or ENG_x keys. You can also use a percentage filter on the bound html element if you don't want to construct the number% string in the controller function.
Note: this solution uses lodash for the filtering (which tends to be a standard dependency in angular applications, but just so you know...)
angular.module('app', [])
.controller('MainCtrl', function() {
var ctrl = this;
ctrl.devices = [
{Detail_A:'ShowA1',Detail_B:'ShowB1',Status_A:'',Status_B:'OK',Status_C:'',Status_D:'OK',ENG_A:'OK',ENG_B:'OK',ENG_C:'OK'},
{Detail_A:'ShowA2',Detail_B:'ShowB2',Status_A:'OK',Status_B:'OK',Status_C:'OK',Status_D:'OK',ENG_A:'',ENG_B:'',ENG_C:''},
{Detail_A:'ShowA3',Detail_B:'ShowB3',Status_A:'OK',Status_B:'OK',Status_C:'OK',Status_D:'OK',ENG_A:'OK',ENG_B:'OK',ENG_C:'OK'}
];
ctrl.percentComplete = function(keyString, item) {
var statuses = _.filter(_.keys(item), function(key) {
return key.substring(0, keyString.length) === keyString;
});
var okStatuses = _.filter(statuses, function(status) {
return item[status] === 'OK';
});
return okStatuses.length / statuses.length * 100 + '%';
};
});
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="angular.js#1.5.0" data-semver="1.5.0" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>
<script data-require="lodash.js#4.6.1" data-semver="4.6.1" src="https://cdn.jsdelivr.net/lodash/4.6.1/lodash.js"></script>
<link data-require="bootstrap-css#3.3.6" data-semver="3.3.6" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" />
<script src="script.js"></script>
</head>
<body ng-controller="MainCtrl as main">
<div ng-repeat="device in main.devices" class="row">
<div class="col-md-2 col-sm-2 col-xs-2">{{main.percentComplete('Status', device)}}</div>
<div class="col-md-1 col-sm-1 col-xs-2">{{main.percentComplete('ENG', device)}}</div>
<div class="col-md-1 col-sm-1 col-xs-2">{{device.Detail_A}}</div>
<div class="col-md-1 col-sm-1 col-xs-2">{{device.Detail_B}}</div>
</div>
</body>
</html>
I assume you meant something like this?
HTML:
<div ng-repeat="(key,val) in devices" ng-init="calculateValues(key, val)">
<div class="col-md-2">{{foo[key].StatusPercentComplete / foo[key].StatusSize * 100}} %</div>
<div class="col-md-1">{{foo[key].ENGPercentComplete / foo[key].ENGSize * 100}} %</div>
<div class="col-md-1">{{val.Detail_A}}</div>
<div class="col-md-1">{{val.Detail_B}}</div>
</div>
JS:
$scope.foo = [];
$scope.calculateValues = function(key, value){
$scope.foo[key] = {
StatusPercentComplete: 0,
StatusSize: 0,
ENGPercentComplete: 0,
ENGSize: 0
};
for(var property in value){
if(property.indexOf("ENG_") == 0){
$scope.foo[key].ENGPercentComplete += (value[property] == "OK" ? 1 : 0);
$scope.foo[key].ENGSize++;
}
if(property.indexOf("Status_") == 0){
$scope.foo[key].StatusPercentComplete += (value[property] == "OK" ? 1 : 0);
$scope.foo[key].StatusSize++;
}
}
}
Plunker: https://plnkr.co/edit/LjvwhdMvKl9Ntk3q9pbA?p=preview

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