AngularJS - no two way binding for key-value object - angularjs

Just for note, I know nothing about angularJS, I worked with knockoutJS before and when it comes to angular I am just making assumptions.
I have code like this:
angular.module("umbraco").controller("recallCtrl",
function ($scope, $routeParams) {
$scope.dcList = {
key: "value",
abc: "aaaa",
prop: "tadaa!"
}
});
and markup as follows:
<div ng-controller="recallCtrl">
<table class="table table-sm">
<thead>
<tr>
<td></td>
<th>Key</th>
<th>Value</th>
</tr>
</thead>
<tr ng-repeat="(key, value) in dcList">
<td>
</td>
<td>
<input ng-model="key" />
</td>
<td>
<input ng-model="value"/>
</td>
</tr>
</table>
<pre>{{dcList | json}}</pre>
</div>
So shouldn't output of dcList in the end of html change it's values when I edit corresponding inputs which as I assume are bound to object?
If I am doing something wrong, please advise. I want to create object and be able to change its keys and values.

The reason your current code isn't working is because the "key" and "value" variables are scoped within the ng-repeat, and no longer refer directly to the original object.
Keeping the "values" attached is easy, just use dcList[key] instead of value. Adding new keys takes a bit more work; here I've attached an ng-blur to each "key" field which will init a new key when the field blurs. (ng-change would create a new field on every keystroke, which isn't what you want.) Note that when you start typing a new key, its value appears to disappear -- this is because the dcList[key] refers to the new key name immediately. This would be somewhat confusing in a real UI, of course; you'd probably want to code different behavior into the createNewKey function (such copying the old value into the new key, or deleting the original key).
function recallCtrl($scope) {
$scope.dcList = {
key: "value",
abc: "aaaa",
prop: "tadaa!"
}
$scope.createNewKey = function(k) {
$scope.dcList[k]="";
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
<div ng-controller="recallCtrl">
<table class="table table-sm">
<thead>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
</thead>
<tr ng-repeat="(key, value) in dcList">
<td>
<input ng-model="key" ng-blur="createNewKey(key)"/>
</td>
<td>
<input ng-model="dcList[key]"/>
</td>
</tr>
</table>
<pre>{{dcList | json}}</pre>
</div>

please test this code, change in the value corresponding to the key,
angular.module('app', [])
.controller('Controller', function($scope) {
$scope.dcList = {
key: "value",
abc: "aaaa",
prop: "tadaa!"
}
})
<!DOCTYPE html>
<html>
<head>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.min.js"></script>
</head>
<body ng-app="app">
<div ng-controller="Controller">
<table class="table table-sm">
<thead>
<tr>
<td></td>
<th>Key</th>
<th>Value</th>
</tr>
</thead>
<tr ng-repeat="(key, value) in dcList">
<td>
</td>
<td>
<input ng-model="key" disabled/>
</td>
<td>
<input ng-model="dcList[key]" />
</td>
</tr>
</table>
<pre>{{dcList | json}}</pre>
</div>
</body>
</html>
Here is the plunker

Related

cannot get a current page in the smart table tbody

My smart table look like :
<table st-safe-src="input.inputBuckets" st-table="inputBuckets"
class="table">
<thead>
<tr>
<th>Timestamp</th>
<th ng-repeat="row in input.inputSeriesPrinted">{{row}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in inputBuckets track by $index">
<td>{{row.key | date:'yyyy-MM-dd HH:mm:ss'}}</td>
//current page is undefined
<td ng-repeat="item in input.inputData" >{{item[$parent.$index] + (currentPage-1)*10]}}</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="10" class="text-center">
<div st-pagination="" st-items-by-page="10" st-displayed-pages="7"></div>
</td>
</tr>
</tfoot>
</table>
So, because I have ng-repeat inside ng-repeat and use parent index, I need a current page for a new set of items. Without that (only item[$parent.$index]) displays same data for each page. currentPageis undefined. Any suggestion how can I get currentPage inside mine tbody?
EDIT: Codepen example. Here is my example of the problem with printed indexes of out ng-repeat and inner ng-repeat.
Your question is incomplete as you haven't showen us your controller side. So, from what I understood is the answer below.
CurrentPage is Undefined
You haven't defined it in your controller or your data value is undefined.
You can define the name of the index and use it, something like this.
var myApp = angular.module('myApp', []);
function MyCtrl($scope) {
$scope.lines = [{
text: 'Page 1'
}, {
text: 'Page 2'
}];
$scope.someData = [{
text: 'Some Data 1'
}, {
text: 'some data 2'
}];
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<html>
<body ng-app="myApp">
<div ng-controller="MyCtrl">
<div ng-repeat="(pageIndex, line) in lines">
<div class="preview">{{line.text}} Page Index : {{pageIndex}}</div>
<br/>
<div ng-repeat="(dataIndex, data) in someData">
{{someData[pageIndex]}}
Parent Index : {{pageIndex}}
childIndex : {{dataIndex}}
</div>
</div>
</div>
</body>
</html>

Angular - How to update table with new values

I have a table with ng-repeat:
<table>
<tr>
<thead>
<th>key</th>
<th>value</th>
</thead>
</tr>
<tbody ng-repeat = "i in data">
<td>{{i.key}}</td>
<td>{{i.value}}</td>
</tbody>
</table>
The table is populated with data-ng-init, when the user clicks on a button:
<button ng-click="getNewVals()">new values</button>
I get json with new key-value, my question is how to repopulate the table with the new values baes on the key? is there a angular way to do so?
ng-repeat is bound to the model you are iterating over. If you update the model, ng-repeat will re-draw. In your example, whenever $scope.data changes, the ng-repeat will update itself.
Use this way. It's good if you provide your JSON.
<table>
<tr>
<thead>
<th>key</th>
<th>value</th>
</thead>
</tr>
<tbody>
<tr ng-repeat = "(key, val) in data">
<td>{{key}}</td>
<td>{{val}}</td>
</tr>
</tbody>
</table>
Look at the following example:
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.min.js"></script>
</head>
<body ng-app="myApp" ng-controller="myCtrl">
<ul>
<li ng-repeat="x in persons">{{x.name}}, {{x.age}}</li>
</ul>
<button ng-click="changeIt()">Change json</button>
<script>
//1 module declaration
var app = angular.module('myApp', []);
//2 controller declaration
app.controller('myCtrl',function($scope){
$scope.persons = [
{name:"Peter", "age": 23},
{name:"Lina","age":26},
{name:"Robert", "age":33}
];
$scope.changeIt = function(){
$scope.persons = [
{name:"Larry",age: 59},
{name:"Joseph", age: 63},
{name:"Clara", age:71}
];
}
});
</script>
</body>
</html>
Hope it solves your problem.
you writing ng-reapet instead of ng-repeat
try this.
<table>
<tr>
<thead>
<th>key</th>
<th>value</th>
</thead>
</tr>
<tbody ng-repeat = "i in data">
<td>{{i.key}}</td>
<td>{{i.value}}</td>
</tbody>
</table>
<button ng-click="data.push({'key':1,'value':2})">new values</button>

AngularJS ng-show Not Working with ng-click?

i don't understand what my ng-show not working when i click on my button with ng-click...
thanks for help.
<div ng-show="showMe == 1">
<h5>Ajouter</h5>
<input type="texte">
</div>
<table>
<thead>
<tr>
<th>Numéro :</th>
<th>Type de Produit :</th>
</tr>
</thead>
<tbody ng-repeat="product in shopCtrl.tableProduct">
<tr>
<td>{{product.id}}</td>
<td>{{product.name}}</td>
<td class="text-right">
<div>
<button ng-click="showMe = 1">Ajouter</button>
</div>
</td>
</tbody>
</table>
The answer of gtlambert is true. However if you have more than one level of ng-repeat or another directive that does the same thing you'll have trouble.
To not have any trouble use objects like this :
$scope.params = {showMe:0};// init in controller
<div ng-show="params.showMe == 1">
<button ng-click="params.showMe = 1">
This will always works whatever the number of ng-repeat/directive you use.
When you use ng-repeat this creates a new scope. To access the main controller scope from inside the ng-repeat you need to use $parent.
So, change your ng-click to $parent.showMe = 1 and this will fix the problem:
<button ng-click="$parent.showMe = 1">Ajouter</button>
Here you go. I have a working example. showMe becomes a member of your controller.
function ShopController() {
this.showMe = false;
this.tableProduct = [{
id: 1,
name: "Bar"
}];
}
angular.module('app', [])
.controller('ShopController', ShopController);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ShopController as shopCtrl">
<div ng-show="shopCtrl.showMe">
<h5>Ajouter</h5>
<input type="texte">
</div>
<table>
<thead>
<tr>
<th>Numéro :</th>
<th>Type de Produit :</th>
</tr>
</thead>
<tbody ng-repeat="product in shopCtrl.tableProduct">
<tr>
<td>{{product.id}}</td>
<td>{{product.name}}</td>
<td class="text-right">
<div>
<button ng-click="shopCtrl.showMe = true">Ajouter</button>
</div>
</td>
</tbody>
</table>
</div>

angularjs ng-repeat show all list objects

I have this app which lets users create own events and others to register to those events. When creating event you can have as many questions as you like and you can name the questions as you wish. Those will be asked in the registration. App will fetch the names of the questions from the fields and record them in to the entries.
I am having problems to display a table of people that are going to attend. My app is handling one list:
var events = [{
Title: 'Summer Festival',
Date: '12.7.2015',
Location: 'Moon',
Description: Fillertxt,
url: "www.something.com",
MaxEntries: 10,
fields: [{
id: 'choice1',
name: "Gender"
}, {
id: 'choice1',
name: "Address"
}],
entries: []
},
Fields have all the questions and when I add an entry and print it it will show {"Gender":"rr","Address":"rr"} in this case.
The problem is that because I cannot foresee the names of those fields I cannot use ng-repeat and then just say <td>{{event.Gender}}<td>because it might as well be {{event.lifesmeaning}}. So how can i display a nice table with the registration info. Can I fetch those names from the fields somehow? I tried nested ng-repeat but didn't got it to work.
Here is also part of the registration page:
<div class="col-md-4">
<form>
<div class="border-box">
<center>
<h2 class="big">Participate:</h2>
<div data-ng-hide="!listFull()">The registration for this event is full.</div>
<div class="form-group" data-ng-hide="listFull()">
<label for="eventInput">Name</label>
<input style="width: 200px;" type="text" class="form-control" id="eventInput" data-ng-model="newEntry.name">
</div>
<div data-ng-repeat="field in event.fields" data-ng-hide="listFull()">
<div class="form-group">
<label for="{{$index + 1}}">{{field.name}}</label>
<input style="width: 200px;" type="text" class="form-control" id="{{$index + 1}}" data-ng-model="newEntry[field.name]">
</div>
</div>
<button style="width: 100px;" data-ng-click="addEntry()" class="btn btn-primary" data-ng-hide="listFull()">Save</button>
</center>
<br/>
</div>
</form>
<div class="border-box2">
<h2 class="big" align="center">Who is comming:</h2>
<p align="center">{{event.MaxEntries}} can participate.</p>
<table>
<tbody>
<tr data-ng-repeat="entry in event.entries">
<th>{{entry}}</th>
</tr>
</tbody>
</table>
<br/>
<br/>
</div>
</div>
If people are still stumbling upon this post...
1. Simple list of objects
So if you have a list/object of objects that will be populated dynamically, like such:
var list = [
{key1: 'value1'},
{key2: 'value2'}
]
And more key, value pairs will be added going forward (possibly with a push to the list).
In this case, the table body would be constructed as so
<tbody>
<tr ng-repeat="obj in sobjs">
<td ng-repeat="(key, value) in obj">
{{key}}
</td>
<td ng-repeat="(key, value) in obj">
{{value}}
</td>
</tr>
</tbody>
2. That was simple. Instead if you have a more complex structure as so:
var list = [
{'key1': [
{
'skey1':'sval11',
'skey2':'sval12'
},
{
'skey1': 'sval11a',
'skey2': 'sval11b'
}
]},
{'key2': [
{
'skey1':'sval21',
'skey2':'sval22'
},
{
'skey1': 'sval21a',
'skey2': 'sval21b'
}
]}
]
In this case the table body will be constructed as so:
<tbody>
<tr ng-repeat="obj in lobjs">
<td ng-repeat="(key, value) in obj">
{{key}}
</td>
<td ng-repeat="(key, value) in obj">
<table class="table table-bordered">
<thead>
<tr>
<th>
Sub-value 1
</th>
<th>
Sub-value 2
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="sobj in value">
<td>
{{sobj.skey1}}
</td>
<td>
{{sobj.skey2}}
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
Plunker working code: https://plnkr.co/edit/r4naGBaYAufhD073oXdw?p=preview
Code snippet with the same code below
function Ctrl($scope) {
$scope.sobjs = [{
'key1': 'value1'
}, {
'key2': 'value2'
}]
$scope.lobjs = [{
'key1': [{
'skey1': 'sval11',
'skey2': 'sval12'
}, {
'skey1': 'sval11a',
'skey2': 'sval11b'
}]
}, {
'key2': [{
'skey1': 'sval21',
'skey2': 'sval22'
}, {
'skey1': 'sval21a',
'skey2': 'sval21b'
}]
}]
}
<!DOCTYPE html>
<html ng-app="">
<head>
<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 data-require="angular.js#1.2.7" data-semver="1.2.7" src="https://code.angularjs.org/1.2.7/angular.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<div ng-controller="Ctrl">
<h2>Simple List of Objects</h2>
<table class="table table-bordered">
<thead>
<tr>
<th>
Key
</th>
<th>
Value
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="obj in sobjs">
<td ng-repeat="(key, value) in obj">
{{key}}
</td>
<td ng-repeat="(key, value) in obj">
{{value}}
</td>
</tr>
</tbody>
</table>
<h2>List of Objects with a list of objects as values for each key</h2>
<table class="table table-bordered">
<thead>
<tr>
<th>
Key
</th>
<th>
Value
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="obj in lobjs">
<td ng-repeat="(key, value) in obj">
{{key}}
</td>
<td ng-repeat="(key, value) in obj">
<table class="table table-bordered">
<thead>
<tr>
<th>
Sub-value 1
</th>
<th>
Sub-value 2
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="sobj in value">
<td>
{{sobj.skey1}}
</td>
<td>
{{sobj.skey2}}
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
Write an array of arrays and keep both field and value as element of array. Something like this :
var sample = [ [ sampleField, sampleValue ], [ anotherSampleField , anotherSampleValue ] ];
Now you can iterate using ng-repeat as :
<li ng-repeat = "index in sample"> index[0] : index[1]</li>

Hiding the table columns and rows using AngularJs

I have checkboxes with table headers, i want to hide the table columns and rows based on the checkbox click,
<ul>
<li ng-repeat="opt in fieldvalues"><input type="checkbox" ng-model="checked" value="{{opt}}" />{{opt}}</li>
</ul>
<table>
<tr>
<th ng-show="checked=='true'">Activity ID</a></th>
<th>Activity Description</th>
</tr>
<tr ng-repeat="nm in makerQueueData">
<td ng-show="checked=='true'">{{nm.formattedIdentifier}}</td>
<td>{{nm.description}}</td>
</tr>
</table>
I tried but no luck.
<ul>
<li ng-repeat="opt in fieldvalues"><input type="checkbox" ng-model="checked" value="{{opt}}" />{{opt}}</li>
</ul>
<table>
<tr>
<th ng-show="checked"><a>Activity ID</a></th>
//here checked gets bool value itself based on selection. you don't need to compare it to string 'true'.
//keep in mind i assume {{checked}} returns only bool value
<th>Activity Description</th>
</tr>
<tr ng-repeat="nm in makerQueueData">
<td ng-show="checked">{{nm.formattedIdentifier}}</td>
<td>{{nm.description}}</td>
</tr>
</table>
Working fiddle for your : http://jsfiddle.net/b69pkeLd/1/
Let me know if any issue occurs.
I hope this is what you are looking for:
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.fieldvalues = [
{text: 'Test1', checked: false},
{text: 'Test2', checked: false}
];
$scope.makerQueueData = [
'Whatever your', 'data is'
];
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<div ng-repeat="opt in fieldvalues">
<input type="checkbox" id="checkbox-{{$index}}" ng-model="opt.checked" value="{{opt.text}}" />
<label for="checkbox-{{$index}}">{{opt.text}}</label>
<table ng-show="opt.checked">
<tr>
<th>Activity ID</a></th>
<th>Activity Description</th>
</tr>
<tr ng-repeat="nm in makerQueueData">
<td ng-show="opt.checked'">{{$index}}</td>
<td>{{nm}}</td>
</tr>
</table>
</div>
</div>
Moreover, use <label> for type="checkbox" description. This makes the label clickable.

Resources