Load an observablearray from a URL into a template - json

I am pretty new to knockoutJS, have completed their interactive tutorials, it was extremely informative.
I read a few posts, like :
KnockoutJS observableArray with template and foreach
It was quite helpful but I couldn't grasp the whole concept as to how to apply it in my context, cause I am fetching data from URL.
One way I thought of solving the problem is maybe by nesting templates.
Cause two things need to be done
Send the observable array to template
Loop over each element and access it's property so as to display in the tmplate
ToDo :
Load the observablearray(), got from a JSON into the template.
The output should be like this :
https://screenshots.firefoxusercontent.com/images/c72ec9d9-075b-40d0-b8cb-f3a4eca76c0d.png
The rendering element
<div class="row">
<div class="col-sm-12">
<div id="template_wallet" data-bind="template: { name: 'wallets_display_tmp', data: coins() }"></div>
### Template
<script type="text/html" id="wallets_display_tmp">
<h2>Wallets<br>
</h2>
<hr />
<table class="table table-striped table-hover">
<thead>
<tr>
<th class="text-center">Currency Name</th>
<th class="text-center">Symbol</th>
<th class="text-center">Amount</th>
<th class="text-center">Deposit/Withdraw</th>
</tr>
</thead>
<tbody>
<tr data-bind="foreach: coin()">
<td class="text-center" data-bind="text: name"></td>
<td class="text-center" data-bind="text: symbol"></td>
<td class=" options">
<div class="center-block text-center">
// <button type="button" class="btn btn-primary btn-xs text-center pop" data-toggle="modal" data-target=".modal" style="margin:-6px 2px" data-purpose="deposit" data-coin=<%= wallet.get('name') %>><span class="fa fa-plus"></span></button>
// <button type="button" class="btn btn-primary btn-xs text-center pop" data-toggle="modal" data-target=".modal" style="margin:-6px 2px" data-purpose="withdrawal" data-coin=<%= wallet.get('name') %> ><span class="fa fa-minus"></span></button>
</div>
</td>
<td></td>
</tr>
</tbody>
</table>
</script>
</div>
</div>
</body>
<script>
$(document).ready(function() {
function walletCoin(){
this.name = ko.observable();
this.symbol = ko.observable();
this.balance = ko.observable();
}
function WalletViewModel(){
var self = this;
self.coins = ko.observableArray([]);
$.getJSON("https://api.myjson.com/bins/13ed0p", function(allData){
console.log(allData);
var mappedCoins = $.map(allData, function(item){
return new walletCoin(item);
});
self.coins(mappedCoins);
});
}
// var walletBalance = new WalletViewModel();
// ko.components.register('', {
// template: {element: 'wallets_display_tmp'},
// });
ko.applyBindings(new WalletViewModel(), document.getElementById("template_wallet"));
});
</script>
The JSON data is
[
{
"name": "Bitcoin",
"symbol": "BTC",
"balance": 0.001212
},
{
"name": "Ripple",
"symbol": "XRP",
"balance": 123.1212
},
{
"name": "Litecoin",
"symbol": "LTC",
"balance": 13.1212
},
{
"name": "Digibyte",
"symbol": "DGB",
"balance": 1231.1212
}
]
Update : I have added a knockoutJS context debugger and added ko.toJSON($data)
Currently I am getting output like this :

$(document).ready(function() {
function walletCoin(){
this.name = ko.observable();
this.symbol = ko.observable();
this.balance = ko.observable();
}
function WalletViewModel(){
var self = this;
self.coins = ko.observableArray([]);
$.getJSON("https://api.myjson.com/bins/13ed0p", function(allData){
console.log(allData);
for (var i = allData.length - 1; i >= 0; i--) {
console.log(allData[i]);
var mappedCoins = ko.mapping.fromJS(allData[i], walletCoin);
self.coins.push(mappedCoins);
}
});
console.log(self.coins());
}
ko.applyBindings(new WalletViewModel(), document.getElementById("template_wallet"));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<div class="row">
<div class="col-sm-12">
<hr />
<h2>Debug</h2>
<div data-bind="text: ko.toJSON(WalletViewModel)"></div>
<div id="template_wallet" data-bind="template: { name: 'wallets_display_tmp', foreach:coins }"></div>
<script type="text/html" id="wallets_display_tmp">
<h2>Wallets <br>
<small>Estimated Value: 0.00318249 BTC / 47.39 USD</small>
</h2>
<hr />
<table class="table table-striped table-hover">
<thead>
<tr>
<th class="text-center">Currency Name</th>
<th class="text-center">Symbol</th>
<th class="text-center">Amount</th>
<th class="text-center">Deposit/Withdraw</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center" data-bind="text: name"></td>
<td class="text-center" data-bind="text: symbol"></td>
<td class="text-center" data-bind="text: balance"></td>
<td class=" options">
<div class="center-block text-center">
// <button type="button" class="btn btn-primary btn-xs text-center pop" data-toggle="modal" data-target=".modal" style="margin:-6px 2px" data-purpose="deposit" data-coin=<%= wallet.get('name') %>><span class="fa fa-plus"></span></button>
// <button type="button" class="btn btn-primary btn-xs text-center pop" data-toggle="modal" data-target=".modal" style="margin:-6px 2px" data-purpose="withdrawal" data-coin=<%= wallet.get('name') %> ><span class="fa fa-minus"></span></button>
</div>
</td>
</tr>
</tbody>
</table>
</script>
<!-- <div class="container">
<canvas id="live_exchange_chart"></canvas>
</div> -->
</div>
</div>
Do check this :
<script>
$(document).ready(function() {
function walletCoin(){
this.name = ko.observable();
this.symbol = ko.observable();
this.balance = ko.observable();
}
function WalletViewModel(){
var self = this;
self.coins = ko.observableArray([]);
$.getJSON("https://api.myjson.com/bins/13ed0p", function(allData){
console.log(allData);
for (var i = allData.length - 1; i >= 0; i--) {
console.log(allData[i]);
var mappedCoins = ko.mapping.fromJS(allData[i], walletCoin);
self.coins.push(mappedCoins);
}
});
console.log(self.coins());
}
ko.applyBindings(new WalletViewModel(), document.getElementById("template_wallet"));
});
</script>
Here is the jsfiddle for the same.

self.coins = ko.computed(function () {
var coins = {};
self.days = '';
$.ajax({
type: "GET",
dataType: "json",
url: yoururl,
data: {},
async: false,
success: function (response) {
if (response.items) {
for (var i = 0; i < response.items.length; i++) {
coins[i] = {
name: response.items[i].name,
symbol: response.items[i].symbol,
balance: response.items[i].balance
};
}
}
},
error: function () {
console.log('error');
}
});
return coins;
});
I am not fully understand your question, but i guess you need something like this?

Related

How to deal with checkboxes in html page?

I want to get the output as single row like group name and visible or not. but in my scenario i am getting different output .
enter image description here
Here is my html code.
#model List<F3CentricMVCApp.Areas.KnowledgeBox.Models.GroupResponse>
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
<div class="col-12">
<table id="tblSectionGroups" class="table responsive table-striped" bPaginate="true">
<thead>
<tr>
<th width="95%">Groups</th>
<th width="5%" class="no-sort"></th>
</tr>
</thead>
<tbody>
#if (#ViewBag.UnAssidnedGroups is not null)
{
#foreach (var item in Model)
{
<tr>
<td>#item.Name</td>
#foreach (var unassinedGroup in ViewBag.UnAssidnedGroups)
{
#if (#unassinedGroup.GroupId == #item.Id)
{
<td>
<input type="checkbox" class="chkSectionVisibility" />
</td>
}
else
{
<td>
<input type="checkbox" class="chkSectionVisibility" checked="checked" />
</td>
}
}
</tr>
}
}
</tbody>
</table>
</div>
<script>
$('#tblSectionGroups').DataTable({
"bLengthChange": false,
"pageLength": 5,
"bPaginate": true,
"stripeClasses": [],
"info": false,
language: {
searchPlaceholder: "Type to filter list",
search: ""
},
"order": [],
"columnDefs": [{
"targets": 'no-sort',
"orderable": false,
}]
});
</script>
<div class="col-md-12 text-right">
<button type="button" class="btn btn-custom" tabindex="3" id="btnSave">Save</button>
</div>
Single checkbox for each group in a row is my requirement. any body can guide me how to deal with two collections in a code which is going through 2 foreach statements. but the logic should not be disturbed after all.
Update your foreach code as below i.e.
#if (#ViewBag.UnAssidnedGroups is not null)
{
#foreach (var item in Model)
{
int isUnassigned = 0;
<tr>
<td>#item.Name</td>
#foreach (var unassinedGroup in ViewBag.UnAssidnedGroups)
{
#if (#unassinedGroup.GroupId == #item.Id)
{
<td>
<input type="checkbox" class="chkSectionVisibility" />
</td>
// Setting.
isUnassigned++;
}
}
if (isUnassigned <= 0)
{
<td>
<input type="checkbox" class="chkSectionVisibility" checked="checked" />
</td>
}
</tr>
}
}
Hopefully this will solve your issue.

renderAjax failed to return data

I did this in the past year and it works just fine. Until recently I encounter this problem which I don't know what caused it.
Here I'm trying to pass supplierID from a (1)form through (2)ajax javascript and return the (3)data from AdminController to a (4)div in the same view
(1)form:-
<?php $form = ActiveForm::begin([
'id'=>'chatform'
]);?>
<div class="box-body">
<table id="example1" class="table table-bordered table-striped">
<thead>
<tr>
<th>No</th>
<th>Supplier</th>
<th>Option(s)</th>
</tr>
</thead>
<tbody>
<?php
for($x = 0; $x < count($supplierChatInfoListTable); $x++){ ?>
<tr>
<td>
<?=$x+1?>
<div class="form-group">
<input type="hidden" name="supplierID" id="supplierID" class="form-control"
value="<?=$supplierChatInfoListTable[$x]['supplierID']?>" style="width: 50px">
</div>
</td>
<td >
<h4><?=$supplierChatInfoListTable[$x]['supplierFirstname']?></h4>
</td>
<td>
<button type="button" class="btn btn-primary btnchat"><i class="fa fa-edit"></i></button>
</td>
</tr>
<?php } ?>
</tbody>
<tfoot>
<tr>
<th>No</th>
<th>Supplier</th>
<th>Option(s)</th>
</tr>
</tfoot>
</table>
</div>
<?php ActiveForm::end();?>
and here is my (2)javascript running in the same view:-
<?php
$urproudcode= Url::to(['admin/chatinfo2pass']);
$this->registerJs("
$(function(){
$('.btnchat').click(function(){
var supplierID = $('#supplierID').val();
$.ajax({
'url':'".$urproudcode."',
'data':{supplierID:supplierID},
'method':'POST',
beforeSend: function (xhr) {
$.blockUI({
message: 'Processing...',
css: {
border: 'none',
padding: '15px',
backgroundColor: '#000',
'-webkit-border-radius': '10px',
'-moz-border-radius': '10px',
opacity: .5,
color: '#fff'
}
});
},
'success':function(data){
$('.chatmessages').html('Success');
if(data == 'false'){
$.unblockUI();
$('.chatmessages').html('Data False');
}else{
$.unblockUI();
$('.chatmessages').html(data);
}
},
error: function (xhr, ajaxOptions, thrownError) {
$.unblockUI();
$('.chatmessages').html('Failed');
console.log(data);
}
});
});
});
");
?>
(3)div with class=chatmessages in the same view
<div class="col-md-8 chatmessages">
</div>
(4)actionChatinfo2pass in AdminController
public function actionChatinfo2pass()
{
$postData = \Yii::$app->request->post('supplierID');
$supplierID = intval($postData);
// fetch all supplier for chat
$supplierChatInfoListTable = SupplierProfile::find()
->select(['supplier_profileID AS supplierID','supplier_profile.first_name AS supplierFirstname',
'supplier_profile.middle_name AS supplierMiddlename', 'supplier_profile.last_name AS
supplierLastname', 'login_profile.login_profileID AS loginID', 'status_login.status_loginID AS
statusLoginID', 'status_login.description AS statusLogindesc'])
->leftJoin('login_profile', 'login_profile.login_profileID = supplier_profile.login_profile_ID')
->leftJoin('status_login', 'status_login.status_loginID = login_profile.status_login_ID')
//->where(['=', 'status_login.description', $activeSupplier])
->orderBy(['supplier_profile.supplier_profileID' => SORT_ASC])
->asArray()
->all();
$dataSend['supplierChatInfoListTable'] = $supplierChatInfoListTable;
$this->layout = 'admin/main';
$html= $this->renderAjax('#app/views/admin/displaychatmessage.php',$dataSend);
echo $html;
}
But it return the 'same' supplierID for both supplier as show below:
and browser console give me this error?(updated):-
btw, this is the content of displaychatmessage.php (I just try to display supllierID and their name)
<!-- DIRECT CHAT WARNING -->
<div class="box box-warning direct-chat direct-chat-warning">
<div class="box-header with-border">
<h3 class="box-title">Direct Chat</h3>
<div class="box-tools pull-right">
<span data-toggle="tooltip" title="3 New Messages" class="badge bg-yellow">3</span>
<button type="button" class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i>
</button>
<button type="button" class="btn btn-box-tool" data-toggle="tooltip" title="Contacts" data-widget="chat-pane-toggle">
<i class="fa fa-comments"></i></button>
<button type="button" class="btn btn-box-tool" data-widget="remove"><i class="fa fa-times"></i></button>
</div>
</div>
<!-- /.box-header -->
<div class="box-body">
<!-- Conversations are loaded here -->
<div class="direct-chat-messages">
<!-- Message. Default to the left -->
<div class="direct-chat-msg">
<div class="direct-chat-info clearfix">
<?php for($z = 0; $z < count($supplierChatInfoListTable); $z++){?>
<span class="direct-chat-name pull-left">Supplier ID: <?=$supplierChatInfoListTable[$z]['supplierID']?>, <?=$supplierChatInfoListTable[$z]['supplierFirstname']?> <?=$supplierChatInfoListTable[$z]['supplierMiddlename']?> <?=$supplierChatInfoListTable[$z]['supplierLastname']?></span>
<?php }?>
<span class="direct-chat-timestamp pull-right">23 Jan 2:00 pm</span>
</div>
<!-- /.direct-chat-info -->
<img class="direct-chat-img" src="dist/img/user1-128x128.jpg" alt="Message User Image"><!-- /.direct-chat-img -->
<div class="direct-chat-text">
Is this template really for free? That's unbelievable!
</div>
<!-- /.direct-chat-text -->
</div>
<!-- /.direct-chat-msg -->
<!-- Message to the right -->
<div class="direct-chat-msg right">
<div class="direct-chat-info clearfix">
<span class="direct-chat-name pull-right">Sarah Bullock</span>
<span class="direct-chat-timestamp pull-left">23 Jan 2:05 pm</span>
</div>
<!-- /.direct-chat-info -->
<img class="direct-chat-img" src="dist/img/user3-128x128.jpg" alt="Message User Image"><!-- /.direct-chat-img -->
<div class="direct-chat-text">
You better believe it!
</div>
<!-- /.direct-chat-text -->
</div>
<!-- /.direct-chat-msg -->
</div>
<!--/.direct-chat-messages-->
<!-- Contacts are loaded here -->
<div class="direct-chat-contacts">
<ul class="contacts-list">
<li>
<a href="#">
<img class="contacts-list-img" src="dist/img/user1-128x128.jpg" alt="User Image">
<div class="contacts-list-info">
<span class="contacts-list-name">
Count Dracula
<small class="contacts-list-date pull-right">2/28/2015</small>
</span>
<span class="contacts-list-msg">How have you been? I was...</span>
</div>
<!-- /.contacts-list-info -->
</a>
</li>
<!-- End Contact Item -->
</ul>
<!-- /.contatcts-list -->
</div>
<!-- /.direct-chat-pane -->
</div>
<!-- /.box-body -->
<div class="box-footer">
<form action="#" method="post">
<div class="input-group">
<input type="text" name="message" placeholder="Type Message ..." class="form-control">
<span class="input-group-btn">
<button type="submit" class="btn btn-warning btn-flat">Send</button>
</span>
</div>
</form>
</div>
<!-- /.box-footer-->
</div>
<!--/.direct-chat -->
Can you help me with this? I don't know where it went wrong.
As you have mentioned you are getting same supplierID on clicking both supplier. This problem is caused because in your js code you are getting supplierID by id of the input i.e '#supplierID', and according to your html code the input elements of both of the suppliers have same value in their id attribute i.e 'supplierID', because of that every time js will get value from first input element with id attribute value 'supplierID'. So you need to make some changes in your html and js code. As there is separate edit button for each supplier so instead of using input to store supplierID value you can store it in a data attribute in the edit button. So your updated html code would become
<?php $form = ActiveForm::begin([
'id'=>'chatform'
]);?>
<div class="box-body">
<table id="example1" class="table table-bordered table-striped">
<thead>
<tr>
<th>No</th>
<th>Supplier</th>
<th>Option(s)</th>
</tr>
</thead>
<tbody>
<?php
for($x = 0; $x < count($supplierChatInfoListTable); $x++){
$supID = $supplierChatInfoListTable[$x]['supplierID']; ?>
<tr>
<td>
<?=$x+1?>
<div class="form-group">
<input type="hidden" name="<?='supplierID'.$supID?>" id="<?='supplierID'.$supID?>" class="form-control"
value="<?=$supID?>" style="width: 50px">
</div>
</td>
<td >
<h4><?=$supplierChatInfoListTable[$x]['supplierFirstname']?></h4>
</td>
<td>
<button type="button" class="btn btn-primary btnchat" data-supplierID="<?=$supID?>"><i class="fa fa-edit"></i></button>
</td>
</tr>
<?php } ?>
</tbody>
<tfoot>
<tr>
<th>No</th>
<th>Supplier</th>
<th>Option(s)</th>
</tr>
</tfoot>
</table>
</div>
<?php ActiveForm::end();?>
And then get the supplierID of clicked supplier from data attribute of button in js. So your js code would become
<?php
$urproudcode= Url::to(['admin/chatinfo2pass']);
$this->registerJs("
$(function(){
$('.btnchat').click(function(){
var supplierID = $(this).attr('data-supplierID');
$.ajax({
'url':'".$urproudcode."',
'data':{supplierID:supplierID},
'method':'POST',
beforeSend: function (xhr) {
$.blockUI({
message: 'Processing...',
css: {
border: 'none',
padding: '15px',
backgroundColor: '#000',
'-webkit-border-radius': '10px',
'-moz-border-radius': '10px',
opacity: .5,
color: '#fff'
}
});
},
'success':function(data){
$('.chatmessages').html('Success');
if(data == 'false'){
$.unblockUI();
$('.chatmessages').html('Data False');
}else{
$.unblockUI();
$('.chatmessages').html(data);
}
},
error: function (xhr, ajaxOptions, thrownError) {
$.unblockUI();
$('.chatmessages').html('Failed');
console.log(data);
}
});
});
});
");
?>
I hope your problem will be solved.

angularjs div's duplicating. every next button controls a corresponding div

I have such a simplified markup which appends and fills in every next row by surname and name; also by clicking the "List" button I need to fill in additional data about this person in a new popup div and save all information into LocalStorage.
The problem is when I click on different "List" buttons appears and hides the same div but the task is:
by clicking on different "List" buttons appear and hide different divs(clones).
Your support highly appreciated.
var app = angular.module("myApp",['listOfBooks']);
app.controller("myCtrl", function($scope){
$scope.authors = [];
$scope.addAuthor = function(){
var author = {};
author.surname = "";
author.name = "";
$scope.authors.push(author);
};
});
var app = angular.module("listOfBooks",[]);
app.controller("booksCtrl", function($scope){
$scope.showBooks = false;
$scope.showBookList = function(){
$scope.showBooks = !$scope.showBooks;
}
$scope.books = [];
$scope.addBook = function(){
var book = {};
book.title = "";
$scope.books.push(book);
};
});
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body ng-app="myApp" ng-controller="myCtrl">
<div class="container">
<h3>AUTHORS' LIST</h3>
<div class="btn-group">
<button ng-click ="addAuthor()" type="button" class="btn btn-default">Add</button>
</div>
<form ng-controller="booksCtrl" name ="myForm">
<table class="table table-bordered">
<tr>
<th>Surname</th>
<th>Name</th>
<th>Books</th>
</tr>
<tr ng-repeat="author in authors">
<td><input ng-model="author.surname" type="text" class="form-control"></td>
<td><input ng-model="author.name" type="text" class="form-control"></td>
<td>
<button ng-click="showBookList()" type="button" class="btn btn-default">List</button>
</td>
</tr>
</table>
<div ng-show="showBooks" class="col-sm-8" style="background-color:lightblue; position: absolute; left:5px; top:5px;z-index:2;">
<div class="btn-group">
<button ng-click ="addBook()" type="button" class="btn btn-default">Add</button>
</div>
<table class="table table-bordered">
<tr>
<th>Title</th>
</tr>
<tr ng-repeat="book in books">
<td><input ng-model="book.title" type="text" class="form-control"></td>
</tr>
</table>
</div>
</form>
</div>
</body>
</html>
I understand the question to be around how should you add a list of books with respect to the author. The current code creates a list of books, but does not allow the books to associate to a given author. I've done this with minimal changes, aside from adding a section to display the contents of the author array. I also added a simple close button within the list div for easier use.
This example takes advantage of the existing authors array that you have, and adds a child array under the books property. When you add an author, and then add a book, the property will be created if it does not already exist.
var app = angular.module("myApp", ['listOfBooks']);
app.controller("myCtrl", function($scope) {
$scope.authors = [];
$scope.addAuthor = function() {
var author = {};
author.surname = "";
author.name = "";
$scope.authors.push(author);
};
});
var app = angular.module("listOfBooks", []);
app.controller("booksCtrl", function($scope) {
$scope.showBooks = false;
$scope.currentAuthor = {};
$scope.showBookList = function(author) {
$scope.showBooks = !$scope.showBooks;
$scope.currentAuthor = author;
}
$scope.addBook = function() {
// If the current author doesn't have a books array yet, create an empty one.
$scope.currentAuthor.books = $scope.currentAuthor.books || [];
var book = {};
book.title = "";
$scope.currentAuthor.books.push(book);
};
});
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body ng-app="myApp" ng-controller="myCtrl">
<div class="container">
<h3>AUTHORS' LIST</h3>
<div class="btn-group">
<button ng-click="addAuthor()" type="button" class="btn btn-default">Add</button>
</div>
<form ng-controller="booksCtrl" name="myForm">
<table class="table table-bordered">
<tr>
<th>Surname</th>
<th>Name</th>
<th>Books</th>
</tr>
<tr ng-repeat="author in authors">
<td><input ng-model="author.surname" type="text" class="form-control"></td>
<td><input ng-model="author.name" type="text" class="form-control"></td>
<td>
<button ng-click="showBookList(author)" type="button" class="btn btn-default">List</button>
</td>
</tr>
</table>
<div ng-show="showBooks" class="col-sm-8" style="background-color:lightblue; position: absolute; left:5px; top:5px;z-index:2;">
<div class="btn-group">
<button ng-click="addBook()" type="button" class="btn btn-default">Add</button>
</div>
<table class="table table-bordered">
<tr>
<th>Title</th>
</tr>
<tr ng-repeat="book in currentAuthor.books">
<td><input ng-model="book.title" type="text" class="form-control"></td>
</tr>
</table>
<button class="btn btn-sm btn-warning" ng-click="showBooks = false">Close</button>
</div>
</form>
</div>
<hr />
<h2>authors data</h2>
<ul>
<li ng-repeat="a in authors">
Surname: {{ a.surname }}, Name: {{ a.name }}
<ul>
<li ng-repeat="b in a.books">Book: {{ b.title }}</li>
</ul>
</li>
</ul>
</body>
</html>

How to create dynamic scope variables in Angularjs?

I want create the screen like this.
The select dropdowns and input fields should not effect on each other (right now if I select company, that is showing as selected in the next set, it should not like that). How can I implement this?
'use strict';
angular.module('newmonthlyplanning.controllers', [])
.controller('newmonthlyplanningCtrl', ['$scope','$window', '$state', 'serviceFactory', '$compile', '$interval','targetPlanningService',
function ($scope,$window,$state, serviceFactory, $compile,$interval,targetPlanningService) {
$scope.status = '200';
$scope.months = ['Jan','Feb','Mar','Apr','May','June','July','Aug','Sep','Oct','Nov','Dec'];
$scope.getAllSectors = function(){
targetPlanningService.getAllsectors().then(function (response) {
$scope.status = response.status;
console.log(response);
if (response.status === 200) {
$scope.sectors = response.data.sector_list;
}
else {
}
}, function (response) {
console.log(response);
if (response.status === 401) {
$state.go('login');
}
});
};
$scope.getcustomers = function(sector){
console.log("selected sector ",sector);
targetPlanningService.getAllCustomers(sector).then(function (response) {
$scope.status = response.status;
console.log(response);
if (response.status === 200) {
$scope.customers = response.data.customer_list;
}
else {
}
}, function (response) {
console.log(response);
if (response.status === 401) {
$state.go('login');
}
});
};
$scope.targetDetails = [];
$scope.getAllCompanies = function(){
targetPlanningService.getAllCompanies().then(function (response) {
$scope.status = response.status;
console.log("companies---> ",response);
if (response.status === 200) {
$scope.companies = response.data.companies;
$scope.targetDetails.push({'companies':$scope.companies,'sectors': $scope.sectors ,'customers': $scope.customers ,'targetss': $scope.targets});
}
else {
}
}, function (response) {
console.log(response);
if (response.status === 401) {
$state.go('login');
}
});
};
$scope.getAllproductIds = function(){
/* var details = {
'company' : $scope.targetDetails.company,
'sector' : $scope.targetDetails.sector
}
console.log("details--->",details);*/
console.log("$scope.targetDetails.company--->",$scope.targetDetails.company);
targetPlanningService.getAllproductIds($scope.targetDetails.company).then(function (response) {
$scope.status = response.status;
console.log("product_ids--->",response);
if (response.status === 200) {
$scope.productids = response.data.item_list;
}
else
{
}
}, function (response) {
console.log(response);
if (response.status === 401) {
$state.go('login');
}
});
};
$scope.targets = [{'pid': '','week1': '', 'week2': '','week3':'','week4':''}];
var i=1;
$scope.addNewChoice = function(id) {
$scope.targetDetails;
i++;
$scope.targets.push({'pid': '','week1': '', 'week2': '','week3':'','week4':''});
};
$scope.removeChoice = function(val) {
console.log("index------>",val);
$scope.targets.splice(val,1);
};
//$scope.targetDetails = [];
console.log("companies at targetDetails------>",$scope.companies);
var i =0;
$scope.addorder = function(){
var object = {};
object['targetss'] = $scope.targets;
// $scope.targetDetails.push({'companies':$scope.companies,'sectors': $scope.sectors ,'customers': '','targetss': $scope.targets});
$scope.targetDetails.push(object);
};
$scope.init = function () {
console.log("present state...",$state.current.name);
if($state.current.name==="monthly"){
$scope.getAllSectors();
// $scope.getnumberOfweeks();
$scope.getAllCompanies();
// $scope.getTargetDetails();
//$scope.getCommentDetails();
}
};
$scope.init();
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12" style="padding: 0px" ng-repeat="details in targetDetails">
<div class="row">
<table class="table table-bordered">
<thead>
<tr>
<th>Company</th>
<th>Sector</th>
<th>Customer</th>
</tr>
</thead>
<tbody>
<tr >
<td>
<div>
<select class="form-control" data-ng-model="targetDetails.company" ng-change="getAllproductIds()" style="border: 1px solid skyblue;">
<option value="">Select Company</option>
<option ng-repeat="company in details.companies track by $index" value="{{company}}" >{{company}}</option>
</select>
</div>
</td>
<td >
<div >
<select class="form-control" data-ng-model="targetDetails.sector" ng-change="getcustomers(targetDetails.sector)" style="border: 1px solid skyblue;">
<option value="">Select Sector</option>
<option ng-repeat=" sector in details.sectors track by $index" value="{{sector}}">{{sector}}</option>
</select>
</div>
</td>
<td>
<div >
<select class="form-control" data-ng-model="targetDetails.customer" style="border: 1px solid skyblue;">
<option value="Customer"> Customer</option>
<option ng-repeat=" customer in details.customers track by $index" value="{{customer}}">{{customer}}</option>
</select>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="row" style="padding: 0px">
<table class="table table-bordered">
<thead>
<tr>
<th>Product Id</th>
<th >WEEK1</th>
<th >WEEK2</th>
<th >WEEK3</th>
<th >WEEK4</th>
<!-- <th>Total</th> -->
<!-- <th>Status</th> -->
<th >Action</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="target in details.targetss">
<td align="center" >
<select class="form-control" style="width: 120px;border: 1px solid skyblue;" data-ng-model="target.pid" ng-change="getUnitsofProduct(target.pid)">
<option value="">Select pid</option>
<option data-ng-repeat="pid in productids">{{pid}}</option>
</select>
</td>
<td align="center">
<input class="form-control" style="width: 70px" type="text" name="" ng-model="target.week1">
</td>
<td align="center">
<input class="form-control" style="width: 70px" type="text" name="" ng-model="target.week2">
</td>
<td align="center">
<input class="form-control" style="width: 70px" type="text" name="" ng-model="target.week3">
</td>
<td align="center">
<input class="form-control" style="width: 70px" type="text" name="" ng-model="target.week4">
</td>
<!-- <td align="center" >
{{ (target.week1 * 1) + (target.week2 * 1)+ (target.week3 * 1)+ (target.week4 *1)+ (target.week5 *1) }} {{target.uom}}
</td> -->
<!-- <td ng-if="target.status==''"></td>
<td ng-if="target.status==='Pending'"><span style="color: blue">{{target.status}}</span></td>
<td ng-if="target.status==='Rejected'"><span style="color: red">{{target.status}}</span></td>
<td ng-if="target.status==='Accepted'"><span style="color: green">{{target.status}}</span></td> -->
<td align="center">
<button class="add" style="background-color: #008CBA;" data-ng-show="$last" data-ng-click="addNewChoice($parent.$index)">+</button>
<button class="sub" data-ng-click="removeChoice($index)" style="background-color:#f44336;margin:0px;">-</button>
</td>
<td>{{$parent.$index}}</td>
</tr>
</tbody>
</table>
<br>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12" style="padding: 0px">
<div class="col-xs-1 col-sm-1 col-md-1 col-lg-1" >
<button data-ng-click="addorder()" style=" padding: 5px;margin: 0px">Add Order</button>
</div>
</div>
</div>
You can use $index for the purpose.
For example:
<select class="form-control" data-ng-model="targetDetails.company[$index]" ng-change="getAllproductIds()" style="border: 1px solid skyblue;">
<option value="">Select Company</option>
<option ng-repeat="company in details.companies track by $index" value="{{company}}" >{{company}}</option>
</select>
Use in ng-model:
data-ng-model = "targetDetails.company[$index]"
Hope this helps.

AngularJS processing input value

When i start typing a name of student, like "M", the list of student needs to include only students, name of that are starting on letter "M" and so on rest of the word. But input value .length is undefined all the time.
(function() {
var app = angular.module('app', []);
app.controller('DataController', function() {
this.students = arr;
this.compare = function() {
for (var i = 0; i < this.text.length; i++) {
if (this.text[i] == this.students.name[i]) {
alert(this.text);
return true;
}
}
}
});
var arr= [{
name: 'Azurite',
price: 2.95
}, {
name: 'Bloodstone',
price: 5.95
}, {
name: 'Zircon',
price: 3.95
}];
}());
HTML
<div class="container-fluid">
<div class="row-fluid">
<input class="col-md-12 col-xs-12" type="text" placeholder="Search people by name..." ng-model='text' ng-change='data.students.name'>
<div class="buttons">
<button class="btn btn-sort">Sort by name</button>
<button class="btn btn-sort">Sort by age</button>
<button ng-click='data.click()' class="btn btn-danger">Reset</button>
</div>
</div>
<!--Main content-->
<div class="main-table col-sm-8 col-md-7 col-md-offset-1 col-lg-7 col-lg-offset-1">
<table class="table table-hover">
<thead>
<tr>
<th class="text-center">Image</th>
<th>Name</th>
<th>Age</th>
<th>Phone</th>
</tr>
</thead>
<tbody ng-repeat='student in data.students' ng-show='data.compare()'>
<tr>
<td>
<img src="/img/cat.svg" alt="">
</td>
<td>{{student.name}}</td>
<td>41</td>
<td>sieg#example.com</td>
</tr>
</tbody>
</table>
</div>
</div>
The angular way to do this is to use the filter feature built in to angular.
first, the text box you want to type your search into:
<input class="col-md-12 col-xs-12" type="text"
placeholder="Search people by name..." ng-model='data.text'>
Note that this only needs an ng-model value.
Next, the ng-repeat:
<tbody ng-repeat='student in data.students | filter:data.text'>
Nothing is necessary at all in the controller.
http://plnkr.co/edit/aoR2ZkrgjCvhC60Ky0QA?p=preview