Pushing Object to array does not reflect at ng-repeat - angularjs

I am updating an array by pushing the Json object returned by MVC controller to an array in Angular JS controller.
Following is the code sports-controller.js
portsApp.controller("SportsController", ["$scope","$http",function ($scope,$http) {
$scope.data = { id: "rehmat" };
$scope.sports = [];
$scope.selectedSport ={};
$scope.sportsObj = {};
$scope.SportsModel = {};
$scope.sport = {};
$scope.remoteUrlRequestFn = function (str) {
return { term: str };
};
function genericSuccess(res) {
return res.data; // yes, really.
}
$scope.selectedSport = function (selected) {
$scope.sport =
{
title: selected.originalObject.name,
parent_id: selected.originalObject.parent,
sports_id: selected.originalObject.sports_id,
user_id: selected.originalObject.uid
}
$http.post("/usersports/post_sport", $scope.sport).then(function (data, status, headers, config) {
$scope.sports.push(genericSuccess(data).sport);
console.log($scope.sports);
});
}
$scope.UpdateSport = function (id) {
if(id > 0)
{
$http.post("/usersports/update_sports", { user_sport_id: id }).then(function (data,status,headers,config){
if(data.Success)
{
alert(data.Message)
}else
{
alert(data.Message)
}
})
}
}
}
])
VIEW :
<div class="container sports-c" ng-app="SportsApp" >
<!--ADD SPORTS TEXT-->
<div class="col-lg-12" ng-controller="SportsController">
{{sports}}
<div class="add-sports-text ">
<h1 style="text-align:center;" class="animated jello">ADD SPORTS</h1>
<hr style="width:30%">
<p>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s,
</p>
</div>
<div class="form-group" style="text-align:center;">
<label for="search" style="text-align:center;"> SEARCH</label>
<angucomplete-alt id="sports_input_box"
placeholder="Search Sports"
pause="400"
selected-object="selectedSport"
remote-url="/ajax/getSports"
remote-url-request-formatter="remoteUrlRequestFn"
remote-url-data-field="items"
title-field="name"
minlength="2"
input-class="form-control input-custom" />
#*<input type="Search" placeholder="SEARCH" class="form-control input-custom" id="sports_input_box">*#
</div>
</div>
<div class="col-lg-12">
<div class="table-responsive">
{{sports.length}}
<table class="table table-bordered " id="sports-table">
<tr>
<td>ID</td>
<td>SPORTS NAME</td>
<td>SELECT SKILL LEVEL</td>
<td>ACTION</td>
</tr>
<tbody>
<tr ng-repeat="item in sports">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td style="position: relative;top: 10px;">
<select class="example" name="" ng-change="updatePlayerSkill(item.id)" ng-bind="SportsModel.skill_level">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</td>
<td class="icons-tab">
<i class="fa fa-check-square-o" aria-hidden="true" ng-click="UpdateSport(item.id)"></i>
<i class="fa fa-trash-o" aria-hidden="true" ng-click="RemoveSport(item.id)"></i>
</td>
</tr>
<tr ng-show="sports.length === 0"><td colspan="5">No Sports Added</td></tr>
</tbody>
</table>
</div>
</div>
</div>
What is a possible solution for this since I am updating the array by pushing the elements and its not reflecting?
I am using Angular Js 1.6, any help would be really appreciated.
please check the image

Try to surround the code that is pushing the element in the array with a $timeout (Don't forget to inject the $timeout in your controller). This will trigger the diggest cycle and update the bindings, as can be seen here.
`
$http.post("/usersports/post_sport", $scope.sport).then(function (data, status, headers, config) {
$timeout(function(){
$scope.sports.push(genericSuccess(data).sport);
console.log($scope.sports);
});
});
`

The error is caused because from what I see in angucomplete-alt library, the selected parameter can be null. You need to handle that:
$scope.countrySelected = function(selected) {
if (selected) {
window.alert('You have selected ' + selected.title);
} else {
console.log('cleared');
}
};
Regarding your primary question. Using asynchronus requests, it could happen that you go out of Angular $digest cycle. Try to wrap array.push with $scope.applyAsync() to refresh the view.

Related

angularjs dropdown menu: populate two input fields with different information from one option

I am brand new to AngularJS. I'm wanting to select an option from the dropdown RegistrationType and want that selection to determine what populates its own input AND input RegAmount.
So, I select the first option, $155.00 Two Day and "$155.00" would show up in the RegAmount input and "Two Day" should show up in the RegistrationType input.
I have failed multiple times, so far, over the last two days. Any advice is appreciated. One thing I tried was adding a name/id to the option and trying to tie that to RegAmount, but I wasn't able to separate the information.
I also tried a ng-if by duplicating the RegAmount div to show "$155.00" if the first option was selected, and ng-if if it wasn't selected, to show "$95.00". Couldn't get that to work either. Oh, and NO, RegAmount should not be an input of course, but I just hadn't changed it yet.
function ContactController($scope) {
$scope.changeme = function() {
}
var uid = 1;
$scope.contacts = [{
id: 0,
'regType': '5555',
'RegistrationType': '5555'
}];
$scope.saveContact = function() {
if ($scope.newcontact.id == null) {
$scope.newcontact.id = uid++;
$scope.contacts.push($scope.newcontact);
} else {
for (var i in $scope.contacts) {
if ($scope.contacts[i].id == $scope.newcontact.id) {
$scope.contacts[i] = $scope.newcontact;
}
}
}
$scope.newcontact = {};
}
$scope.delete = function(id) {
for (var i in $scope.contacts) {
if ($scope.contacts[i].id == id) {
$scope.contacts.splice(i, 1);
$scope.newcontact = {};
}
}
}
$scope.edit = function(id) {
for (i in $scope.contacts) {
if ($scope.contacts[i].id == id) {
$scope.newcontact = angular.copy($scope.contacts[i]);
}
}
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"></script>
<div ng-app="" ng-controller="ContactController">
<form class="well">
<div>
<label>Registration Type</label>
<select name="RegistrationType" ng-model="newcontact.RegistrationType">
<option value = "">-- Select an Option --</option>
<option value = "Two Day">$155.00 Two Day</option>
<option value = "First Day">$95.00 First Day</option>
<option value = "Second Day">$95.00 Second Day</option>
</select>
</div>
<div>
<label>Registration Amount</label>
<input type="text" name="Registration Amount" ng-model="newcontact.RegAmount" />
</div>
<br>
<div>
<input type="hidden" ng-model="newcontact.id" />
<input id="buttonSave" type="button" value="Save" ng-click="saveContact()" class="btn btn-primary" />
<p style="clear: both;"></p>
</div>
</form>
<br/>
<br/>
<table>
<thead>
<tr>
<th>Registration Type</th>
<th>Registration Amount</th>
<th>Edit | Delete</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="contact in contacts">
<td>{{ contact.RegistrationType }}</td>
<td>{{ contact.RegAmount }}</td>
<td>
edit |
delete
</td>
</tr>
</tbody>
</table>
You could use NgOptions to solve this, here's an example
angular.module("app",[]).controller('testCtrl' , function($scope) {
var uid = 1;
$scope.newcontact = {};
$scope.days = [
{ id:1, text:"$155.00 Two Day (Now to 8 p.m. Sept 10)", price:"$155.00", day:"Two Day" },
{ id:2, text:"$95.00 First Day (Now to 8 p.m. Sept 10)", price:"$95.00", day:"First Day" },
{ id:3, text:"$95.00 Second Day (Now to 8 p.m. Sept 10)", price:"$95.00", day:"Second Day" }
];
$scope.contacts = [];
$scope.saveContact = function() {
if ($scope.newcontact.id == null) {
$scope.newcontact.id = uid++;
$scope.contacts.push($scope.newcontact);
} else {
for (var i in $scope.contacts) {
if ($scope.contacts[i].id == $scope.newcontact.id) {
$scope.contacts[i] = $scope.newcontact;
}
}
}
$scope.newcontact = {};
}
$scope.delete = function(id) {
for (var i in $scope.contacts) {
if ($scope.contacts[i].id == id) {
$scope.contacts.splice(i, 1);
$scope.newcontact = {};
}
}
}
$scope.edit = function(id) {
for (i in $scope.contacts) {
if ($scope.contacts[i].id == id) {
$scope.newcontact = angular.copy($scope.contacts[i]);
}
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"></script>
<div ng-app="app" ng-controller="testCtrl">
<form class="well">
<div>
<label>Registration Type</label>
<select ng-model="newcontact.RegistrationType" ng-options="item as item.text for item in days">
<option value = "">-- Select an Option --</option>
</select>
</div>
<div>
<label>Registration Amount</label>
<input type="text" name="Registration Amount" ng-model="newcontact.RegistrationType.price" />
</div>
<br>
<div>
<input id="buttonSave" type="button" value="Save" ng-click="saveContact()" class="btn btn-primary" />
<p style="clear: both;"></p>
</div>
</form>
<br/>
<br/>
<table>
<thead>
<tr>
<th>Registration Type</th>
<th>Registration Amount</th>
<th>Edit | Delete</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="contact in contacts">
<td>{{ contact.RegistrationType.text }}</td>
<td>{{ contact.RegistrationType.price }}</td>
<td>
edit |
delete
</td>
</tr>
</tbody>
</table>

How to avoid loading data from server every time doing sorting/paging with ngtable

I am using ngtable (1.0.0) to display records fetched from server side. My controller js looks like this:
ristoreApp.controller("fmCtrl",
['$scope', '$filter', 'fmFactory', 'NgTableParams', function($scope, $filter, fmFactory, NgTableParams) {
var self = this;
$scope.selection = '0';
$scope.fmSearch = function () {
if ($scope.selection == '0') {
self.tableParams = new NgTableParams({
page: 1, // show first page
count: 10, // count per page
sorting: {
frReportId: 'asc'
}
}, {
getData: function (params) {
return fmFactory.getAll()
.then(function(response) {
var reports = response.data;
params.total(reports.length);
console.log(params.total());
var sorted = params.sorting() ? $filter('orderBy')(reports, params.orderBy()) : reports;
return sorted.slice((params.page() - 1) * params.count(), params.page() * params.count());
});
}
});
}
}
}]
)
HTML for the table:
<div ng-controller="fmCtrl as fm">
<div class="container">
<div class="row top-margin-80">
<div class="col-md-12">
<div class="input-group" id="adv-search">
<input type="text" class="form-control" ng-model="keyword" placeholder="Enter MRN or report ID" />
<div class="input-group-btn">
<div class="btn-group" role="group">
<div class="dropdown dropdown-lg">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false"><span class="caret"></span></button>
<div class="dropdown-menu dropdown-menu-right" role="menu">
<form class="form-horizontal" role="form">
<div class="form-group">
<label for="filter">Search by</label>
<select class="form-control" ng-model="selection">
<option value="0" selected>All Reports</option>
<option value="1" >MRN</option>
<option value="2">ReportID</option>
</select>
</div>
<div class="form-group">
<input class="form-control" type="text" ng-model="optionword" ng-hide="selection == '0'"/>
</div>
</form>
</div>
</div>
<button type="button" class="btn btn-primary" ng-click="fmSearch()"><span class="glyphicon glyphicon-search" aria-hidden="true"></span></button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<table ng-table="fm.tableParams" class="table table-bordered table-striped table-condensed" show-filter="false">
<tr ng-repeat="report in $data">
<td data-title="'ReportId'" filter="{frReportId: 'text'}" sortable="'frReportId'" class="text-center">
{{report.frReportId}}</td>
<td data-title="'BlockId'" filter="{frBlockId: 'text'}" sortable="'frBlockId'" class="text-center">
{{report.frBlockId}}</td>
<td data-title="'MRN'" filter="{mrn: 'text'}" sortable="'mrn'" class="text-center">
{{report.mrn}}</td>
<td data-title="'Name'" filter="{frFullName: 'text'}" sortable="'frFullName'" class="text-center">
{{report.frFullName}}</td>
<td data-title="'Diagnosis'" filter="{frDiagnosis: 'text'}" sortable="'frDiagnosis'" class="text-center">
{{report.frDiagnosis}}</td>
<td data-title="'File'" class="text-center"><a ng-href="{{report.filepath}}">{{report.frReportId}}.xml</a>
</td>
</tr>
</table>
</div>
</div>
It works, well sort of. Problem is whenever I click on the titles to sort and page button to go to next page, it makes an ajax call to server to retrieve data again. I have over 2000 records in the database, every time I do something to the table, it takes 5 seconds to respond which is very annoying. How do I make it load the data only the first time and cache it on client side for future manipulation?
Finally got it to work. Solution is to move the ajax call var Ajax = fmFactory.getAll(); outside ngtable constructor.
var Ajax = fmFactory.getAll();
self.tableParams = new NgTableParams({
page: 1, // show first page
count: 10, // count per page
sorting: {
frReportId: 'asc'
}
}, {
getData: function (params) {
return Ajax.then(function(response) {
var reports = response.data;
params.total(reports.length);
console.log(params.total());
var sorted = params.sorting() ? $filter('orderBy')(reports, params.orderBy()) : reports;
return sorted.slice((params.page() - 1) * params.count(), params.page() * params.count());
});
}
});

AngularJS Service not calling controller to get updated data after CRUD operation

I am beginner in AngularJS and trying to create a master data entry screen, where upper portion containing form fields & lower portion containing table(GridView) to display all master entries. Grid showing all the data when i initially run the application. If i add/Edit any new/old records, the updated data not reflected in the gridview. (i.e) If i add any new entry, it is saving into the DB through service, but not reflecting in the GridView. Even if i navigate through menu also not displaying the updated data in the grid. But if i press Ctrl + F5, it is showing updated data in the Grid. Alsp If i close the browser & re run the application then the updated records displaying in the Gridview. Below is my code. Please help.. Thank you.!
Index.cshtml
<div class="row">
<div class="col-md-12">
<h3 class="page-header">
Component Master
</h3>
<div class="col-md-12">
<div class="alert alert-dismissible alert-danger" ng-show="ComponentForm.$invalid && submitted">
<button type="button" class="close" aria-hidden="true" data-dismiss="alert">
×</button>
<p ng-show="ComponentForm.ComponentName.$error.required && (ComponentForm.ComponentName.$dirty || submitted)">
- Component Name is required.</p>
<p ng-show="ComponentForm.ComponentName.$error.minlength && (ComponentForm.ComponentName.$dirty || submitted)">
- Component Name should be minimum 5 char long.</p>
<p ng-show="ComponentForm.Language.$error.required && (ComponentForm.Language.$dirty || submitted)">
- Language Selection is required.</p>
</div>
</div>
<div class="col-md-12">
<div class="panel panel-success">
<div class="panel-heading">
<h3 class="panel-title">
Panel success</h3>
</div>
<div class="panel-body">
<div class="row">
<div class="col-lg-12">
<!-- FORM : YOU CAN DISABLE, HTML5 VALIDATION BY USING "novalidate" ATTRIBUTE-->
<form name="ComponentForm" class="form-inline" novalidate>
<!-- COMPONENT NAME -->
<div class="form-group" ng-class="{ 'has-error' : ComponentForm.ComponentName.$invalid && (ComponentForm.ComponentName.$dirty || submitted) }"
style="margin: 10px;">
<label style="margin-right: 10px;">
Component Name</label>
<input type="text" name="ComponentName" ng-model="ComponentModel.ComponentName" class="form-control"
placeholder="Component Name..." ng-minlength="5" ng-required="true" />
<input type="hidden" data-ng-model="ComponentModel.ComponentID" />
<input type="hidden" data-ng-model="ComponentModel.IsActive" />
<input type="hidden" data-ng-model="UserID" />
</div>
<!-- LANGUAGE -->
<div class="form-group" style="margin: 10px;" ng-class="{ 'has-error' : ComponentForm.Language.$invalid && (ComponentForm.Language.$dirty || submitted) }">
<label style="margin-right: 10px;">
Language</label>
<select name="Language" data-ng-model="ComponentModel.Language" class="form-control"
ng-required="true">
<option value="" title="Select">Select</option>
<option value="English" title="English">English</option>
<option value="Spanish" title="Spanish">Spanish</option>
</select>
</div>
<!-- ng-disabled FOR ENABLING AND DISABLING SUBMIT BUTTON -->
<!-- SAVE BUTTON -->
#*<button type="submit" class="btn btn-info" ng-disabled="ComponentForm.$invalid" value="Add">Add</button>*#
<button type="submit" class="btn btn-primary" ng-click="SaveComponent(ComponentModel);"
ng-value="Add">
Add
</button>
<button type="submit" class="btn btn-warning" ng-click="ClearComponent();" value="Clear">
Clear
</button>
</form>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-12">
<table class="table table-striped table-bordered table-hover">
<thead>
<tr class="success">
<th class="text-center">
ComponentID
</th>
<th class="text-center">
Component Name
</th>
<th class="text-center">
Language
</th>
<th class="text-center">
IsActive
</th>
<th class="text-center">
Last Modified By
</th>
<th class="text-center">
Last Modified Date
</th>
<th class="text-center">
Action
</th>
</tr>
<tr style="height: 250px; border: 2px solid #ecf0f1;" data-ng-show="ShowEmptyRow">
<th colspan="7" class="text-center" style="vertical-align: middle;">
<label class="control-label">
No Records Found.</label>
</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="Component in ComponentMaster" data-ng-show="!ShowEmptyRow" ng-class="{'danger':!Component.IsActive}">
<td style="vertical-align: middle; text-align: center;">
{{ Component.ComponentID}}
</td>
<td style="vertical-align: middle;">
{{ Component.ComponentName}}
</td>
<td style="vertical-align: middle;">
{{ Component.Language}}
</td>
<td style="vertical-align: middle; text-align: center;">
<div class="checkbox">
<label>
<input type="checkbox" disabled="disabled" ng-checked="Component.IsActive" /></label>
</div>
</td>
<td style="vertical-align: middle;">
{{ Component.ModifiedBy}}
</td>
<td style="vertical-align: middle; text-align: center;">
{{ Component.ModifiedDate}}
</td>
<th style="vertical-align: middle; text-align: center;">
<span class="btn btn-info btn-sm" ng-show="Component.IsActive" ng-click="EditComponent(Component.ComponentID);">
Edit</span> <span class="btn btn-danger btn-sm" ng-show="Component.IsActive" ng-click="ActivateDeActivateComponent(Component.ComponentID,false,ComponentModel.ModifiedBy);">
Delete</span> <span class="btn btn-info btn-sm" ng-show="!Component.IsActive" ng-click="ActivateDeActivateComponent(Component.ComponentID,true,ComponentModel.ModifiedBy);">
Activate</span>
</th>
</tr>
</tbody>
</table>
</div>
</div>
</div>
Angular Script:
var AngularApp = angular.module("AngularApp", ['ngRoute']);
AngularApp.controller("ConfigurationController", ['$scope', 'ConfigurationService', function ($scope, ConfigurationService) {
$scope.ComponentMaster = [];
GetComponentMasterDetails();
/*------------- Save Component ---------------- */
// When i click Save btn - executing this function. control comes here...
$scope.SaveComponent = function (ComponentModel) {
$scope.submitted = true;
if ($scope.ComponentForm.$valid) {
ComponentModel.ModifiedBy = $scope.UserID;
// control comes here... & Calling method "SaveComponentMaster" inside ConfigurationService & returned execution message
var Msg = ConfigurationService.SaveComponentMaster(ComponentModel);
Msg.then(function (response) {
if (response.data != "") {
alert(response.data);
}
else {
// After Saved into DB showing below alert message.
alert("Data Saved Successfully.");
// Calling below method to get the updated records from DB
GetComponentMasterDetails();
}
}, function (error) {
alert(error.data);
});
}
else {
alert("Please correct errors!");
}
}
/**----------------------------------------------------- */
// Below method is calling...
function GetComponentMasterDetails() {
// Call moves to ConfigurationService Service method...
var ComponentMaster = ConfigurationService.GetComponentMasterDetails();
ComponentMaster.then(function (response) {
if (response.data != "") {
// This service call returning the old data only.
// Updated/Added entry details not reflecting in the returned object.
// This is the reason why it is showing old records only in the Grid.
$scope.ShowEmptyRow = false;
$scope.ComponentMaster.length = 0;
angular.extend($scope.ComponentMaster, response.data);
}
else {
$scope.ShowEmptyRow = true;
$scope.ComponentMaster.length = 0;
}
}, function (error) {
alert(error.data);
});
}
} ]);
AngularApp.service("ConfigurationService", function ($http) {
// Call comes here...
this.GetComponentMasterDetails = function () {
// Call comes here... But this $http.get - not calling MVC controller Action method.
// I kept my breakpoint in MVC controller method, but not executed the method.
// So this Service just returning old records. This is the reason the View showing old records.
// If i press Ctrl + F5, it is calling MVC controller message & showing the updated records.
return $http.get('/Configuration/GetComponentMasterDetails');
};
// Control comes here... Then calling MVC controller Action method.. Saving data into DB & returned execution message.
this.SaveComponentMaster = function (ComponentModel) {
var response = $http({
method: 'POST',
url: '/Configuration/SaveComponentMaster/',
data: { ComponentModel: ComponentModel }
});
return response;
};
});
MVC Controller
[NoCache]
[HttpGet]
public ActionResult GetComponentMasterDetails()
{
RNDDBContext dbContext = new RNDDBContext();
var result = dbContext.ExecuteStoreQuery<ComponentModel>("exec PROC_GET_COMPONENT_MASTER_DETAILS").ToList();
return Json(result, JsonRequestBehavior.AllowGet);
}
[NoCache]
[HttpPost]
public JsonResult SaveComponentMaster(ComponentModel ComponentModel)
{
RNDDBContext dbContext = new RNDDBContext();
var result = dbContext.ExecuteStoreQuery<string>("exec PROC_SAVE_COMPONENT_MASTER #ComponentID,#ComponentName,#Language,#IsActive,#ModifiedBy",
new SqlParameter("ComponentID", ComponentModel.ComponentID),
new SqlParameter("ComponentName", ComponentModel.ComponentName),
new SqlParameter("Language", ComponentModel.Language),
new SqlParameter("IsActive", ComponentModel.IsActive),
new SqlParameter("ModifiedBy", ComponentModel.ModifiedBy)
).FirstOrDefault();
return Json(result, JsonRequestBehavior.AllowGet);
}
public class NoCache : ActionFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
filterContext.HttpContext.Response.Cache.SetValidUntilExpires(false);
filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
filterContext.HttpContext.Response.Cache.SetNoStore();
base.OnResultExecuting(filterContext);
}
}
Initialize your $scope.ComponentMaster on the top of controller
AngularApp.controller("ConfigurationController", ['$scope', 'ConfigurationService', function ($scope, ConfigurationService) {
$scope.ComponentMaster = [];
GetComponentMasterDetails();
and just empty that, then repopulate once you call GetComponentMasterDetails()
function GetComponentMasterDetails() {
var ComponentMaster = ConfigurationService.GetComponentMasterDetails();
ComponentMaster.then(function (response) {
if (response.data != "") {
$scope.ShowEmptyRow = false;
// Empty the ComponentMaster array
$scope.ComponentMaster.length = 0;
// Add the retrieved data
angular.extend($scope.ComponentMaster, response.data)
}
else {
$scope.ShowEmptyRow = true;
// Empty the ComponentMaster array
$scope.ComponentMaster.length = 0;
}
}, function (error) {
alert(error.data);
});
}
This issue is similar to this

Is there a way in Angular to create a duplicate row in ng-repeat?

I have a method where I iterate through an array, using ng-repeat and pair each item with a value from a dropdown list.
Here is a jsfiddle of that method:
https://jsfiddle.net/4zbvv5gq/4/
<header>
<title>myTittle</title>
</header>
<body ng-app='myApp' ng-controller='myController'>
<div class="col-md-10 col-md-offset-1">
<div>
<form>
<table class="table table-striped">
<thead>
<th>From File</th>
<th>Map To</th>
</thead>
<tr class="selector-row" ng-repeat="(key,value) in List1">
<td><span id="myspan">{{value}}</span>
</td>
<td style="padding:10px;">
<select name="repeatSelect" id="repeatSelect" ng-model="data[value]" class="form-control">
<option ng-repeat="(key,value) in Match" value="{{value}}">{{value}}</option>
</select>
</td>
</tr>
</table>
</form>{{ data }}</div>
</div>
</body>
var app = angular.module('myApp', [])
app.controller('myController', ['$scope', function ($scope) {
$scope.data = {};
$scope.List1 = ['product1', 'product2', 'product3', 'product4', 'product5'];
$scope.Match = ['match1', 'match2', 'match3', 'match4', 'match5'];
}])
My challenge is I want to be able to let a user click on something like an "add" link in any of the rows and 1)create a duplicate of that row, then 2) select a different value from the select list.
You just need to add a "Add Row" button at the end and push a new value to your List1 like this in your controller. See an update to your fiddle here.
$scope.addRow = function(){
var len = $scope.List1.length;
$scope.List1.push('product'+(len+1));
}
And right after your table, add a button that calls the above function:
</table>
<button ng-click="addRow()">Add a row</button>
Dublicate row in angular is possible.I give an sample code for dublicate row
index.html part:
<body ng-controller="MyCtrl">
<div style="padding: 10px;">
<h2>Languages</h2>
<br/>
<div style="width: 90%; display: inline-block; border: 1px silver dotted;">
<div class="row">
<div class="col-xs-3">
<select class="form-control" ng-init="nativeLanguage.level = 'Native'" data-ng-model="nativeLanguage.level" tooltip="Level">
<option value="Native" ng-selected="true">Native</option>
</select>
</div>
<div class="col-xs-4">
<select class="form-control" data-ng-model="nativeLanguage.name" tooltip="Language">
<option value="">Language</option>
<option value="EN">English</option>
<option value="IT">Italian</option>
<option value="DE">German</option>
<option value="FR">French</option>
</select>
</div>
<div class="col-xs-3">
<input type="text" data-ng-model="nativeLanguage.remark" class="form-control" placeholder="Remark" tooltip="Remark">
</div>
<div class="col-xs-2">
</div>
</div>
<div select-last ng-repeat='language in languages'></div>
</div>
<a class="btn" style="margin-bottom: 27px;" href="#" tooltip="Add" ng-click='addRow()'>
<i class="glyphicon glyphicon-plus"></i>
</a>
<pre>{{nativeLanguage | json}}</pre>
<pre>{{languages | json}}</pre>
</div>
</body>
</html>
ap.js part:
var myApp = angular.module('myApp',[]);
myApp.directive('selectLast', function () {
return {
restrict: 'A',
transclude: true,
templateUrl: 'language.html',
/*scope: {
level: '=',
name: '=',
remark: '='
},*/
replace: true
};
});
function MyCtrl($scope) {
$scope.languages = [];
/*var nativeLanguage = {
level: $scope.hr.language.level,
name: $scope.hr.language.name,
remark: $scope.hr.language.remark
};*/
$scope.languages.push($scope.nativeLanguage);
$scope.addRow = function(){
var newLanguage = {
level: $scope.level,
name: $scope.name,
remark: $scope.remark
};
$scope.languages.push(newLanguage);
console.log('+ clicked');
};
$scope.deleteRow = function(rowNo) {
/*$scope.items.splice($scope.newitem);*/
$scope.languages.splice(rowNo, 1);
console.log('- clicked in row ' + rowNo);
};
}

List does not refresh in AngularJS

I'm trying to implement a simple crud using Google App Engine (Cloud endpoints) and AngularJs.
I developed my backend and everything working well. My problem is Angular.
After I call my service to Save or Delete, my list doesn't refresh.
My code Controller:
app.controller('admEstadoController',['$scope','admEstadoService', function ($scope, admEstadoService) {
$scope.saveEstado = function() {
admEstadoService.saveEstado($scope);
}
$scope.deleteEstado = function(id) {
admEstadoService.deleteEstado(id,$scope);
}
$scope.listEstado = function() {
admEstadoService.listEstado($scope);
}
}]);
and this is my Service:
app.factory('admEstadoService',[function() {
var admEstadoService = {};
admEstadoService.listEstado = function($scope) {
gapi.client.enadepopapi.listEstado().execute(function(resp) {
$scope.estados = resp.items;
$scope.$apply();
});
}
admEstadoService.saveEstado = function($scope) {
estado = {
"estado" : $scope.estado,
"nome" : $scope.nome
};
gapi.client.enadepopapi.saveEstado(estado).execute();
}
admEstadoService.deleteEstado = function(id,$scope) {
estado = {
"estado" : id
};
gapi.client.enadepopapi.deleteEstado(estado).execute();
}
return admEstadoService;
}]);
And my view is:
<div class="panel panel-default" ng-show="is_backend_ready">
<div class="panel-heading">Manutenção de Estados</div>
<div class="panel-body">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<form role="form">
<div class="form-group">
<label for="txtEstado">Estado</label>
<input type="text" class="form-control" id="txtEstado" placeholder="" ng-model="estado">
</div>
<div class="form-group">
<label for="txtNome">Nome</label>
<input type="text" class="form-control" id="txtNome" placeholder="" ng-model="nome">
</div>
<button type="submit" ng-click="saveEstado()" class="btn btn-default">Gravar</button>
</form>
<div class="bs-example-bg-classes" style="margin-top:10px;">
<p class="bg-success"> Registro Gravado com sucesso!</p>
</div>
<div class="clearfix"></div>
<div ng-init="listEstado()">
<table class="table table-hover">
<tbody class="table-hover">
<tr>
<th>Estado</th>
<th>Nome</th>
<th>Operação</th>
</tr>
<tr ng-repeat="estado in estados">
<td>{{estado.estado}}</td>
<td>{{estado.nome}}</td>
<td><button type="button" ng-click="deleteEstado(estado.estado)" class="btn btn-default">Excluir</button>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
Even though you update the data in the backend, AngularJS is not aware of this. You need to call listEstado() after save or delete.
However, if you're using ndb as your datastore, be aware that your updated data may not be available instantly because of ndb's eventual consistency behavior.

Resources