I am writing and application using AngularJs, HTML and PHP. In the application I have a dropdown list, which when an option is selected a table is populated with related data drawn from a database. I can add to or delete info from the table. That works perfectly. However, the challenge I have is that each time the table is edited, the web page refreshes/route is reloaded and the drop down list returns to its default value. The effect of this is the user having to manually reselect the dropdown list value to carryout each operation on the table. How can I alter the code to keep/persist the last selected option value and have the said dropdown list option selected when the webpage/route reloads?
I have seen many help responses to setting initial default value for dropdown lists. However that is not what I am trying to achieve. I am trying to set the post reload value or value after the webpage reloads.
Below is a part of what I have tried. I am at my whits end trying to figure it out. Any help is appreciated.
EDIT
Problem Solved
HTML before changes
<select id="b_year" ng-options="b.year for b in budgets track by b.year" ng-model="b.selectedBudget" ng-change="getBudgetItems(b.selectedBudget.year)" required><option value="">-- Choose budget year --</option></select>
HTML with solution changes
<select id="b_year" ng-options="b.year for b in budgets" ng-model="b.selectedBudget" ng-init="b.selectedBudget" ng-selected="getBudgetItems(b.selectedBudget.year)" required><option value="">-- Choose budget year --</option></select>
Controller snippet before changes
$scope.reloadRoute();
$scope.items.push({'line_item': li.line_item, 'weight': li.weight, 'allocated': li.allocated});
localStorage['b_year'] = year; //Store the selected year in local storage for later use
budget_size = server.getBudgetSize();
for(var i = 0; i < budget_size; i++){
if($scope.budgets[i].year === localStorage['b_year']){
$scope.b.selectedBudget[i] = localStorage['b_year'];
}else{
}
}
Controller with solution changes
app.controller(.... {
....
(function(){
$http.get( //Get info on budgets
"http://localhost/TrGway/getbudgetinfo.php"
)
.success(function(data){
$scope.budgets = data.budgets;
for(var i = 0; i < data.budgets.length; i++){
if($scope.budgets[i].year === selectedYear){
$scope.b = {};
$scope.b.selectedBudget = $scope.budgets[i];
}
}
})
.error(function(data){
$scope.message = "Error!! Getting Budget Info Failed: " + data;
});
})();
....
$scope.$watch("b.selectedBudget.year", function(item) {
localStorage.setItem("selectedYear", item);
});
});
App.controller('budgetCtrl', ['$scope', '$http', '$location', '$window', '$route', 'BudgetService', function($scope, $http, $location, $window, $route, BudgetService){
(function(){
$http.get( //Get info on budgets
"http://localhost/TrGway/getbudgetinfo.php"
)
.success(function(data){
server.setBudgets(data.budgets);//Set the budget info in the BudgetService for
//later usage anywhere in the program;
$scope.budgets = data.budgets;
budget_size = server.getBudgetSize();
server.getBudgetInfo();
})
.error(function(data){
$scope.message = "Error!! Getting Budget Info Failed: " + data;
});
})();
(function(){ //Get Line Items Info to populate the table
$http.get(
"http://localhost/TrGway/lineItemInfo.php"
)
.success(function(data){
server.setLineItems(data.items);
$scope.items = data.items;
server.getLineItemsInfo();
})
.error(function(data){
$scope.message = "Error!! Getting Line Items Info Failed: "+data;
});
})();
$scope.addBudget = function(budget){
if( budget.year < new Date().getFullYear() ){
alert("Budgets cannot be created retroactively.\n\
\nPlease enter a budget year greater than "+ new Date().getFullYear() );
$scope.budget.year = "";
}else{
server.addBudget(budget);
server.getBudgetInfo();
$scope.budgets = server.getBudgets();
$scope.budget = {};//Clear the add budget form
}
};
$scope.getBudgetItems = function(year){
/*This is where info on the budget for the selected year is retrieved and passed to the table
This works great every time*/
if( year === undefined ){ //If no year is selected do nothing
$scope.budget_amount = 0;
$scope.budget_amount_used = 0;
$scope.budget_amount_remaining = 0;
}else{
Budgets = server.getBudgets();
budget_size = server.getBudgetSize();
for(var i = 0; i < budget_size; i++){
if(Budgets[i].year === year){
$scope.budget_amount = Budgets[i].starting_amount;
$scope.budget_amount_used = Budgets[i].amount_used;
$scope.budget_amount_remaining = Budgets[i].running_balance;
amount_remaining = Budgets[i].starting_amount - Budgets[i].amount_used;
percent_used += (Budgets[i].amount_used / Budgets[i].starting_amount * 100);
server.setSelectedBudget(Budgets[i]);
}else{
//$scope.budget_amount = 0;
}
}
server.setPercentUsed(percent_used);
server.setPercentRemaining( 100 - percent_used);
server.setAmountRemaining(amount_remaining);
}
};
/*======================= THIS IS WHERE THE CHALLENGE IS ====================*/
$scope.addLineItem = function(li, b){
/*This is where the List items are added to the table before page reload*/
if(($scope.budget_amount_used-0 + li.allocated-0) > $scope.budget_amount){
alert("Budgeted amount exceeded!!!\nPlease consider revising");
$location.path('editbudget');
$scope.li.weight = 0;
$scope.li.allocation = 0;
}else{
server.setSelectedBudgetYear(b.selectedBudget.year); //Save selected year to a variable
server.addLineItem(li, b); //Add the new Line items row to database
$scope.reloadRoute();
$scope.items.push({'line_item': li.line_item, 'weight': li.weight, 'allocated': li.allocated});
$scope.b = {};
//$scope.b.selectedBudget = localStorage.getItem("selected");
$scope.$watch("b.selectedBudget.year", function(item) {
localStorage.setItem("selected", item);
});
//$scope.b.selectedBudget.year = server.getSelectedBudgetYear(); //I tried this also
}
$scope.li.line_item = "";
$scope.li.weight = 0;
$scope.li.allocation = 0;
$scope.b.selectedBudget = localStorage.getItem("selected");
/* LEAVING THIS SO YOU CAN SEE WHAT ELSE I HAVE TRIED
$scope.b = {};
$scope.b.selectedBudget = localStorage.getItem("selectedBudget");
$scope.watch("b.selected", function(item) {
localStorage.setItem("selected", item);
});
$scope.b.selectedBudget = localStorage['b_year'];
*/
/* LEAVING THIS SO YOU CAN SEE WHAT ELSE I HAVE TRIED
budget_size = server.getBudgetSize();
for(var i = 0; i < budget_size; i++){
if($scope.budgets[i].year === server.getSelectedBudgetYear()){
$scope.b.selectedBudget.year = server.getSelectedBudgetYear();
}else{
}
}*/
};
$scope.deleteLineItem = function(row, b){
$http({
method: "post",
url: "http://localhost/TrGway/deleteLineItem.php",
crossDomain: true,
data:{
'seq': row.seq,
'year': row.year,
'allocated':row.allocated,
'starting_amount': b.selectedBudget.starting_amount,
'amount_used': b.selectedBudget.amount_used,
'running_balance': b.selectedBudget.running_balance
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.success(function(response){
if(response.toString() === "success"){
var index = -1;
var itemsArr = eval( $scope.items );
for( var i = 0; i < itemsArr.length; i++ ) {
if( itemsArr[i].seq === row.seq ) {
index = i;
break;
}
}
if( index === -1 ) {
alert( "Something has gone wrong!!\nLine item was not deleted.\nPlease try again" );
}
server.reset();
server.reload();
$scope.budget_percent_used = server.getPercentUsed()-0;
$scope.budget_percent_remaining = server.getPercentRemaining()-0;
$scope.budget_amount_used = server.getAmountUsed()-0;
$scope.budget_amount_remaining = server.getAmountRemaining()-0;
server.setTotalWeighting($scope.totalweighting + row.weight)-0;
server.setPercentUsed(server.getTotalWeighting())-0;
server.setPercentRemaining(100 - server.getPercentUsed())-0;
$scope.items.splice( index, 1 ); //Remove the row with matching index/seq value
$scope.totalweighting = server.getTotalWeighting();
$scope.budget_percent_used = server.getPercentUsed()-0;
$scope.budget_percent_remaining = server.getPercentRemaining()-0;*/
$scope.reloadRoute();
}else{ //If deleting the line item failed
$location.path('editbudget');
$scope.budgetmessage = "Line Item Update Failed: "+response;
}
})
.error(function(response){ //If there was an error connecting to the server
$scope.budgetmessage = "Error!! Updating Line Item Failed: "+response;
});
row.isEditing = false;
};
$scope.updateLineItem = function(row){
$http({
method: "post",
url: "http://localhost/TrGway/updateLineItem.php",
crossDomain: true,
data:{
'seq': row.seq,
'line_item': row.line_item,
'weight': row.weight,
'allocated': row.allocated
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.success(function(response){
if(response.toString() === "success"){
$location.path('editbudget');
}else{
$location.path('editbudget');
$scope.budgetmessage = "Line Item Update Failed: "+response;
}
})
.error(function(response){
$scope.budgetmessage = "Error!! Updating Line Item Failed: "+response;
});
row.isEditing = false;
};
$scope.cancelLineItemEditing = function(row){
row.isEditing = false;
};
$scope.updateBudget = function(b){
$http({
method: "post",
url: "http://localhost/TrGway/updatebudget.php",
crossDomain: true,
data:{
'year': b.selectedBudget.year,
'starting_amount': b.edit_starting_amount
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.success(function(response){
if(response.toString() === "success"){
server.setStartingAmount(b.edit_starting_amount);
var line_items = server.getLineItems();
var start_amount = server.getStartingAmount();
var total_weight = 0;
var amount_used = 0;
var amount_remaining = 0;
var percent_used = 0;
var percent_remaining = 0;
for(var i = 0; i < line_items.length; i++){
//Update the line items on the page immediately
line_items[i].weight = ( line_items[i].allocated / start_amount) * 100;
total_weight += line_items[i].weight;
amount_used += line_items[i].allocated-0;
//Update the line items in the database immediately
$scope.updateLineItem(line_items[i]);
}
server.load();
percent_used = ( amount_used / start_amount) * 100;
amount_remaining = start_amount - amount_used;
percent_remaining = 100 - percent_used;
server.setLineItems(line_items);
server.setTotalWeighting(total_weight);
server.setAmountUsed(amount_used);
server.setPercentUsed(percent_used);
server.setAmountRemaining(amount_remaining);
server.setPercentRemaining(percent_remaining);
$scope.items = server.getLineItems();
$scope.total = 0;
$scope.total = server.getStartingAmount();
$scope.totalweighting = server.getTotalWeighting()-0;
$scope.budget_amount_used = server.getAmountUsed()-0;
$scope.budget_percent_used = server.getPercentUsed()-0;
$scope.budget_percent_remaining = server.getPercentRemaining()-0;
$scope.budget_amount_remaining = server.getAmountRemaining()-0;
$location.path('editbudget');
}else{
$location.path('editbudget');
$scope.budgetmessage = "Budget Update Failed: "+response;
}
})
.error(function(response){
$scope.budgetmessage = "Error!! Updating Budget Failed: "+response;
});
$scope.b = {};
};
$scope.reloadRoute = function(){
$route.reload();
server.reload();
//alert('Loaded!!');
};
}]);
<div class="breadcrumbs" id="breadcrumbs">
<ul class="breadcrumb">
<li>Home</li>
<li class="active"><a href="">Add/Edit line Items</a></li>
<li style="float: right" ng-controller="authCtrl"><a ng-click="logout();">Logout</a></li>
<li style="float: right"><a href="#/dashboard">Back</a></li>
</ul>
</div>
<div class="row" ng-cloak="" ng-controller="budgetCtrl">
<div class="col-md-5">
<section>
<form name="LineItemForm" class="form-horizontal" role="form">
<fieldset>
<table class="table table-striped">
<thead>
<tr>
<th style="width: 150px" colspan="1">Select Budget Year To Edit Line Items</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="1">
<div class="col-md-7">
<!-- THIS IS WHERE THE YEAR IS SELECTED -->
<select id="b_year" ng-options="b.year for b in budgets track by b.year" ng-model="b.selectedBudget" ng-change="getBudgetItems(b.selectedBudget.year);" ng-selected="" required>
<option value="">-- Choose budget year --</option>
</select>
</div>
</td>
</tr>
<tr>
<th style="width: 150px" colspan="1">{{b.budgetmessage}}</th>
</tr>
<tr>
<td>
<h3>Add Line Item Here</h3>
<div class="form-group">
<label class="col-md-3 control-label no-padding-right" for="line_item">Line Item</label>
<div class="col-md-7">
<input type="text" class="form-control" name="line_item" id="line_item" ng-model="li.line_item" ng-disabled="!b.selectedBudget" required/>
</div>
</div>
<div class="form-group">
<label class="col-md-3 control-label no-padding-right" for="weight">weighting %</label>
<div class="col-md-7">
<input type="number:2" class="form-control" name="weight" id="weight" ng-init="li.weight = 0" ng-model="li.weight" ng-disabled="!b.selectedBudget || !li.line_item || li.line_item.length<5" required/>
</div>
</div>
<div class="form-group">
<label class="col-md-3 control-label no-padding-right" for="allocated">Allocated $</label>
<div class="col-md-7">
<input type="number:2" class="form-control" name="allocated" id="allocated" placeholder="{{li.allocated = (budget_amount * li.weight) / 100 | currency}}" ng-init="li.allocated=0" ng-model="li.allocated" ng-disabled="!b.selectedBudget || !li.weight" required />
</div>
</div>
<div class="form-group" style="padding-right: 100px;">
<span class="lbl col-sm-5"> </span>
<div class="col-md-7 message" >
<span id="message" class="block input-icon input-icon-right">{{message}}</span>
</div>
</div>
<div class="form-group">
<div style="padding-right:100px">
<button type="submit" class="width-35 pull-right btn btn-sm btn-primary" ng-click="addLineItem(li, b)" data-ng-disabled="LineItemForm.$invalid || li.weight===0 || li.line_item.length < 5">
Add Line Item
</button>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</fieldset>
</form>
</section>
</div>
<div>
<section>
<div class="col-lg-14" style="float: right">
<form>
<fieldset>
<table class="table table-striped" >
<thead>
<tr>
<!--<th>Index</th>-->
<th>Line Items</th><th style="width: 150px">% Weighting</th><th style="width: 150px">Allocation $</th><th style="width: 120px">Tasks</th><!---->
</tr>
</thead>
<tbody>
<tr data-ng-repeat="row in items" ng-model="items" ng-if="row.year === b.selectedBudget.year"><!--<td>{{$index+1}}</td>-->
<td title="'Line Item'" ng-switch="row.isEditing" ng-class="line_item.$dirty ? 'bg-warning' : ''" ng-form="name" demo-tracked-table-cell>
<span ng-switch-default class="editable-text">{{row.line_item}}</span>
<div class="controls" ng-class="line_item.$invalid && line_item.$dirty ? 'has-error' : ''" ng-switch-when="true">
<input type="text" name="line_item" ng-model="row.line_item" class="editable-input form-control input-sm" required />
</div>
</td>
<td>{{ row.weight = row.allocated / budget_amount * 100 | number: 2 }}</td>
<td title="'Allocation'" ng-switch="row.isEditing" ng-class="allocated.$dirty ? 'bg-warning' : ''" ng-form="allocated" demo-tracked-table-cell>
<span ng-switch-default class="editable-text">{{ row.allocated | currency }}</span>
<div class="controls" ng-class="allocated.$invalid && allocated.$dirty ? 'has-error' : ''" ng-switch-when="true">
<input type="text" name="allocated" ng-model="row.allocated" class="editable-input form-control input-sm" required/>
</div>
</td>
<td>
<button class="btn btn-primary btn-sm" ng-click="updateLineItem(row)" ng-if="row.isEditing" ng-disabled="rowForm.$pristine || rowForm.$invalid"><span class="glyphicon glyphicon-ok"></span></button>
<button class="btn btn-default btn-sm" ng-click="cancelLineItemEditing(row)" ng-if="row.isEditing"><span class="glyphicon glyphicon-remove"></span></button>
<button class="btn btn-default btn-sm" ng-click="row.isEditing = true" ng-if="!row.isEditing"><span class="glyphicon glyphicon-pencil"></span></button>
<button class="btn btn-danger btn-sm" ng-click="deleteLineItem(row, b)" ng-if="!row.isEditing"><span class="glyphicon glyphicon-trash"></span></button>
</td>
</tr>
<tr>
<td>
<h5>
<span class="block input-icon input-icon-right">
<b>TOTAL (Budget Estimate)</b>
</span>
</h5>
</td>
<td>
<h5>
<span class="block input-icon input-icon-right">
<b>{{ totalweighting = budget_amount > 0 ? 100 : 0 | number:2 }}%</b><!---->
</span>
</h5>
</td>
<td>
<h5>
<span class="block input-icon input-icon-right">
<b>{{ budget_amount | currency }}</b>
</span>
</h5>
</td><td></td>
</tr>
<tr>
<td>
<h5>
<span class="block input-icon input-icon-right">
<b>BUDGET AMOUNT USED</b>
</span>
</h5>
</td>
<td>
<h5>
<span class="block input-icon input-icon-right">
<b>{{ budget_percent_used = budget_amount_used > 0 ? budget_amount_used * 100/budget_amount : 0 | number:2 }}%</b>
<!--Adding the -0 forces the compiler to treat the value as a number-->
</span>
</h5>
</td>
<td>
<h5>
<span class="block input-icon input-icon-right">
<!--{{ budget_amount_used + li.allocated | currency }}-->
<b>{{ budget_amount_used | currency }}</b>
</span>
</h5>
</td><td></td>
</tr>
<tr>
<td>
<h5>
<span class="block input-icon input-icon-right">
<b>BUDGETED AMOUNT REMAINING</b>
</span>
</h5>
</td>
<td>
<h5>
<span class="block input-icon input-icon-right">
<b>{{ budget_percent_remaining = 100 - budget_percent_used | number:2 }}%</b>
<!--Adding the -0 forces the compiler to treat the value as a number-->
</span>
</h5>
</td>
<td>
<h5>
<span class="block input-icon input-icon-right">
<!--{{ budget_amount_remaining - li.allocated | currency }}-->
<b>{{ budget_amount_remaining | currency }}</b>
</span>
</h5>
</td><td></td>
</tr>
</tbody>
</table>
</fieldset>
</form>
</div>
</section>
</div>
</div>