Bind Json in Knockout - javascript

I have to bind the fields "city" of a json type:
{
"italia": [
{
"regione": "Abruzzo",
"capoluoghi": [
{
"citta": "Chieti",
"sigla": "CH"
},
{
"citta": "L'Aquila",
"sigla": "AQ"
},
{
"citta": "Pescara",
"sigla": "PE"
},
{
"citta": "Teramo",
"sigla": "TE"
}
]
},{
"regione": "Basilicata",
"capoluoghi": [
{
"citta": "Matera",
"sigla": "MT"
},
{
"citta": "Potenza",
"sigla": "PZ"
}
]
}, ...
in a 'select' html, via knockout.
I entered the code:
self.provincia = ko.mapping.fromJS([]);
$.getJSON("italia.json", function (data) {
ko.mapping.fromJS(data.italia, {}, self.provincia)
})
and in html:
<div data-bind="with: provincia">
<select class="mm-menu__link" id="Provincia" data-bind:"foreach: capoluoghi">
<option data-bind="text:citta"></option>
</select>
</div>
so as to show all cities, but unfortunately I get nothing!
What did I do wrong?
dave

Tough your question is bit unclear i hope this is what you looking at finally .
view:
<div data-bind="foreach: provincia">
<select class="mm-menu__link" id="Provincia" data-bind="foreach: capoluoghi">
<option data-bind="text:citta"></option>
</select>
</div>
viewModel:
var ViewModel = function () {
var self = this;
self.provincia = ko.observable();
ko.mapping.fromJS(json.italia, {}, self.provincia)
};
ko.applyBindings(new ViewModel());
working sample here
If you want to show all cities in one dropdown check here

Related

Angular ng-option filtering with a condition

The following list want to bind in a drop down with condition type="0"
$scope.ListPrintDestination = [{ id: "0", Name: "Printer",Type:"0" }, { id: "1", Name: "Windows" ,Type:"0"}, { id: "2", Name: "No Print" ,Type:"1"}];
then how will modify below code
<select ng-model="num" ng-options="lst as lst.AcNo for lst in lstPrint track by lst.AcNo">
<option selected="selected">select</option>
</select>
You can use filter for Type='0', and in html iterate on ListPrintDestination.
Demo:
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', function MyCtrl($scope) {
$scope.ListPrintDestination = [{
id: "0",
Name: "Printer",
Type: "0"
}, {
id: "1",
Name: "Windows",
Type: "0"
}, {
id: "2",
Name: "No Print",
Type: "1"
}];
});
<script src="https://code.angularjs.org/1.5.2/angular.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<select ng-model="num" ng-options="lst as lst.Name for lst in ListPrintDestination | filter : {Type : '0'} ">
<option selected="selected">select</option>
</select>
</div>

how to use ng-options and ng-select with json

Can somebody explain how to use ng-options when I have below json:
{
"key1":
{
"name":"test1",
"code":"horizontal",
"fields":[
{
"type":"email"
},
{
"type":"text"
}
]
},
"key2":
{
"name":"test2",
"code":"vertical",
"fields":[
{
"type":"emai"
},
{
"type":"text"
}
]
}
}
and then i try to create select like this
<select name="cert" id="cert" ng-options="item as item[paramm] for item in listcert track by $index"></select>
where "paramm" = $key in json.
I want to see something like this
<select>
<option value="horizontal" label='horizontal'>test1</option>
<option value="vertical" label='vertical'>test2</option>
</select>
I have no idea how it works. Please help...
Is this what you were looking for? The trick here is that your data is not in an array format
var data = {
"key1": {
"name":"test1",
"code":"horizontal",
"fields":
[{
"type":"email",
},{
"type":"text",
}]
}, "key2": {
"name":"test2",
"code":"vertical",
"fields":
[{
"type":"emai",
},{
"type":"text",
}]
}
}
angular.module("app", [])
.controller("MainController", MainController);
function MainController() {
var vm = this;
vm.selected = {};
vm.dataArray = [];
angular.forEach(data, function(value, key) {
vm.dataArray.push(value);
}, data);
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="MainController as main">
<select ng-options="value as value.code for value in main.dataArray track by value.name" ng-model="selected"></select>
<h3>Selected value:</h3>
<pre>{{selected | json}}</pre>
</div>
this may suits for you
<select>
<option ng-repeat="(key, value) in listcert" value="{{value.code}}" >{{value.name}}</option>
</select>

AngularJS: Generate a form dynamically in AngularJS

I am trying to generate a HTML form.
I have an object which contains an array of form elements like
{
"formFields": [
{
"type": "select",
"label": "Fabric",
"name": "fabric",
"options": [
"Georgette",
"Crepe",
"Net",
"Lace"
]
},
{
"type": "text",
"label": "Weight",
"name": "weight",
"options": []
}
]
}
I want to generate a form which has fields in accordance with the above object i.e. it should generate a Select labelled Fabric with drop down options "Georgette","Crepe","Net","Lace" and an input element of type text with label Weight.
What is the best way to do this in AngularJS?
I would make a directive which accepts a form field object as input and $compiles a template based on the input.
Html:
<div my-input="settings"></div>
Js:
angular.module('myApp').directive('myInput', ['$compile', function($compile) {
return {
restrict: 'EA',
require: 'ngModel',
link: linkFn,
scope: {
config: '=myInput'
}
};
function linkFn($scope, $element, $attrs, ngModelCtrl) {
init();
function init() {
$scope.model = {};
var template = getTemplate();
template.attr('ng-model', 'model.value');
$compile(template)($scope, function(clonedElem) {
$element.html(clonedElem);
});
}
function getTemplate() {
switch($scope.config.type) {
case 'text':
return '<input type="text"/>';
case 'select':
return '<input type="select" ng-options="option in config.options">';
}
}
}
}]);
This is from the top of my head so the code might be wrong but you get the idea.
You can refer to the sample here. Please find the code below:
HTML:
<div ng-app="app" ng-controller="test">
<form name="myForm" ng-submit="validateForm(myForm.$valid)">
<div ng-repeat="item in formData.formFields">
<div ng-if="item.type == 'text'">
<label>{{item.label}}: </label>
<input type="{{item.type}}" name="{{item.name}}">
</div>
<div ng-if="item.type == 'select'">
<label>{{item.label}}: </label>
<select name="{{item.name}}">
<option ng-repeat="opt in item.options" value="{{opt}}">{{opt}}</option>
</select>
</div>
<br>
</div>
</form>
</div>
JS:
var app = angular.module('app', []);
app.controller('test', function ($scope) {
$scope.formData = {
"formFields": [
{
"type": "select",
"label": "Fabric",
"name": "fabric",
"options": [
"Georgette",
"Crepe",
"Net",
"Lace"
]
},
{
"type": "text",
"label": "Weight",
"name": "weight",
"options": []
}
]
};
$scope.validateForm = function(isValid){
/*..*/
}
});

Ng-Options in Angular for Arrays and Objects

First of all 2 working solutions:
Example 1 - Array in Controller
$scope.s1 = [
{
"name": "Item1",
"id": 1
},
{
"name": "Item2",
"id": 2
}
];
View 1
<select ng-model="select1" ng-options="foo.id as foo.name for foo in s1">
<option value="">Select a Value</option>
</select>
Example 2 - Object in Controller
The same concept may help you also here, if you know the name of "myS2":
$scope.s2 = {
"myS2": [
{
"name" : "Item1",
"id" : 1
},
{
"name": "Item2",
"id": 2
}
]
};
View 2
<select ng-model="select2" ng-options="foo.id as foo.name for foo in s2.myS2">
<option value="">Select a Value</option>
</select>
Now the question:
$scope.s2 has further objects {myS1:[..] to mySn:[..]} with different names and I want'to use them as option group name? How can I do that in ng-options?
I don't think that you can nest loops in ng-repeat, but, adding just a bit of business logic on your controller you can gain what you want!
hope it helps :)
(function(window, angular) {
function TestCtrl(vm, data) {
var options = [];
for(var group in data) {
if(!data.hasOwnProperty(group)) { continue; }
for(var i = 0, len = data[group].length; i < len; i++) {
var item = data[group][i];
item.group = group;
options.push(item);
}
}
vm.options = options;
vm.current = options[0];
}
angular
.module('test', [])
.value('S2', {
"myS2": [
{
"name" : "Item1 mys2",
"id" : 1
},
{
"name": "Item2 mys2",
"id": 2
}
],
"myS3": [
{
"name" : "Item1 mys3",
"id" : 1
},
{
"name": "Item2 mys3",
"id": 2
}
]
})
.controller('TestCtrl', ['$scope', 'S2', TestCtrl])
;
})(window, window.angular);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<section ng-app="test">
<article ng-controller="TestCtrl">
<select ng-model="current" ng-options="item as item.name group by item.group for item in options">
</select>
</article>
</section>

Binding problems with complex data and autocomplete

I'm using Knockout JS 3.2 and I'd like to use it with autocomplete dropdown. I'm not able to get around two problems.
I simplified the data and code so this runs stand-alone:
<script type="text/javascript">
var data = [
{ "User": { "Id": 1, "DisplayName": "john a" }, "Roles": [{ "Id": 1, "Name": "admins" }, { "Id": 2, "Name": "users" }] },
{ "User": { "Id": 2, "DisplayName": "john b" }, "Roles": [] },
{ "User": { "Id": 3, "DisplayName": "john c" }, "Roles": [{ "Id": 1, "Name": "admins" }] },
{ "User": { "Id": 4, "DisplayName": "john d" }, "Roles": [] },
{ "User": { "Id": 5, "DisplayName": "john e" }, "Roles": [{ "Id": 2, "Name": "users" }] }
];
$(function () {
$("#searchTerm").autocomplete({
source: data,
minLength: 1,
select: function (event, ui) {
if (ui.item) {
var viewModel = ko.mapping.fromJS(ui.item);
ko.cleanNode($("#userDetails")[0]);
ko.applyBindings(viewModel, $("#userDetails")[0]);
}
}
})
.autocomplete("instance")._renderItem = function (ul, item) {
return $("<li>")
.append("<a>" + item.User.DisplayName + "</a>")
.appendTo(ul);
};
});
</script>
<div>Select User: <input id="searchTerm" name="searchTerm" type="text" /></div>
<div id="userDetails">
<div>User: <span data-bind="text: User.DisplayName"></span></div>
<div data-bind="foreach: Roles, visible: Roles().length > 0">
<div><span data-bind="text: Name"></span></div>
</div>
</div>
Problems:
I'd like to show the userDetails div only when it's bound -- hide it on page load. I tried setting style="display:none" and then data-bind="if:User" or data-bind="if:User.Id". Setting display attribute hides the element on load, but it doesn't change on bind.
Roles element binding doesn't work right. On first time that user is selected, the roles show, but they fail to show after changing the user selection.
Instead of always rebinding you need to have a proper view model with a selectedUser property and just update that one in the automcomplete handler.
var viewModel = {
selectedUser: ko.observable()
}
ko.applyBindings(viewModel, $("#userDetails")[0]);
$(function () {
$("#searchTerm").autocomplete({
source: data,
minLength: 1,
select: function (event, ui) {
if (ui.item) {
var user = ko.mapping.fromJS(ui.item);
viewModel.selectedUser(user);
}
}
})
.autocomplete("instance")._renderItem = function (ul, item) {
return $("<li>")
.append("<a>" + item.User.DisplayName + "</a>")
.appendTo(ul);
};
});
With this approach you can use the with binding and it will also solve both of your problems:
<div id="userDetails" data-bind="with: selectedUser">
<div>User: <span data-bind="text: User.DisplayName"></span></div>
<div data-bind="foreach: Roles, visible: Roles().length > 0">
<div><span data-bind="text: Name"></span></div>
</div>
</div>
Demo JSFiddle.

Categories

Resources