Bind JSON to Angularjs input - javascript

I got some JSON like this:
[{
"Id": 0,
"Text": "Item 1",
"Selected": 1
}, {
"Id": 1,
"Text": "Item 2",
"Selected": 1
}]
And an Input like this:
<input type="text"
value="{{question.postObjs}}"
What I want is the only the property "Text" as a list in the input.
Item 1, Item 2, ...
Is this even possible? I trying around like a while, got nothing to work :-(

in your controller :
scope.text = '';
for (var value in scope.question.postObjs){
scope.text = scope.text + value.Text;
}
in your input :
<input type="text" value="{{text}}" />
or
<input type="text" ng-model="text" />

Write a method in AngularController like this
$scope.getText(){
// which will return ["Item1", "Item2"]
}
And in view you can use the method to populate the value.

Related

How best can I querySelectorAll inputs by their name in Javascript

I'm trying to populate an array with html input field names then further match them to json object names to I can assign values into them at once as below
Kindly assist with a proper querySelectorAll(input) to get input fields by their name instead of their class names as the below is doing
var inputs = Array.prototype.slice.call(document.querySelectorAll('input'));
Then reuse in code below
Object.keys(recipient).map(function (dataItem) {
inputs.map(function (inputItem) {
return (inputItem.name === dataItem) ? (inputItem.value = recipient[dataItem]) : false;
});
});
My data looks like so:
"data": {
"type": "beneficiaries",
"id": "C9QV9ZNZ",
"attributes": {
"bank_name": null,
"last_name": "xcxc",
"beneficiary_type": "MT",
"mobile_money_msisdn": null,
"branch_name": null,
"recipient_type": "P",
"first_name": "dfgdf",
"middle_name": null,
"name": "dfgdf xcxc",
"mobile": null,
"account_number": "111111111"
}
The nested loops is overkill. Just loop over the inputs and see if the key exists in the object.
var data = {
name1: 123,
name2: 345,
name3: 678
}
document.querySelectorAll("input[name]").forEach( function (input) {
var name = input.name;
if (data[name]) input.value = data[name]
})
<form>
<input name="name1" />
<input name="name2" />
<input name="name3" />
</form>

Put JSON data with the same name into different divs

I have JSON file with this structure:
{
"launches": [{
"name": "First Name"
}],
"launches": [{
"name": "Second Name"
}],
"launches": [{
"name": "Third Name"
}],
"launches": [{
"name": "Fourth Name"
}]
}
I add the data like this:
$('#div-name').append(d.name);
When this is displayed on a webpage, it is placed in one div with no spaces. I can add a <p> tag to the append, but that still displays ALL the data and creates new divs to display it.
Basically, what I am trying to do is to create a div for each separate "name" value and display only one value per div.
First of all, your "json" is not a valid json, remmeber that in a json object, you can not have duplicated keys. You can easily use an online validator to help you with that... and after you fix it, let's assume that what you actually have is an array of objects like:
[
{"name": "Falcon 9"},
{"name": "Orion"},
{"name": "PSLV"},
{"name": "Soyuz"}
]
with this valid json, you can easily loop trough all the elements like (and take that you are using jQuery):
var json = [ ... ];
$(function() {
$.each(json, function(i, item){
$("p").append("<div>" + item.name + "</div>");
});
});
here's a live test: https://jsbin.com/bixadegeye/1/edit?html,css,js,output
A slightly different way of going about it:
var data = {
"names": [
"Falcon 9",
"Orion",
"PSLV",
"Soyuz"
]
};
$.each( data["names"], function( key, value ) {
$('#div-name').append(value+"<br />");
});

How to make linked(dynamic?) select fields in oracle jet?

Im very new to JS and OJET. I'm using oracle jet to create a form. I need to create two select fields, the firts displays a client's name and the next one must change is values with the selected client's team members.
I have a JSON File with this format:
{
"clients": [
{
"id": "C01",
"name": "Client 1",
"manager": "Manager 1",
"team": [
{
"id": "C1MEM1",
"name": "member 1"
},
{
"id": "C1MEM2",
"name": "member 2"
},
{
"id": "C1MEM3",
"name": "member 3"
},
{
"id": "C1MEM4",
"name": "Member 4"
}
]
},
{
"id": "C02",
"name": "Client 2",
"manager": "Manager 2",
"team": [
{
"id": "C2MEM1",
"name": "member 1"
},
{
"id": "C2MEM2",
"name": "member 2"
},
{
"id": "C2MEM3",
"name": "member 3"
},
{
"id": "C2MEM4",
"name": "member 4"
}
]
}
I managed to create a select field with the clients name:
self.clientsListVal = ko.observableArray(['C01']);
self.clientsList = ko.observableArray();
$.getJSON("http://localhost:8000/js/json/clients.json").
then(function(data){
$.each(data["clients"],function(){
self.clientsList.push({
value: this.id,
label: this.name
});
});
});
Then I tried to get the next select fields this way, but it doesn't work :( :
self.memberList = ko.observableArray();
$.getJSON("http://localhost:8000/js/json/clients.json").
then(function(data){
$.each(data["clients"],function(){
if (this.id === self.clientsListVal ) {
$.each(this["team"], function(){
self.memberList.push({
value: this.id,
label: this.name
});
});
}
});
});
This is the HTML im using:
<div class="oj-applayout-content">
<div role="main" class="oj-hybrid-applayout-content">
<div class="oj-hybrid-padding">
<h3>Dashboard Content Area</h3>
<div>
<label for="clients">Clients</label>
<select id="clients"
data-bind="ojComponent:
{component: 'ojSelect',
options: clientsList,
value: clientsListVal,
rootAttributes: {style:'max-width:20em'}}">
</select>
<label for="select-value">Current selected value is</label>
<span id="select-value" data-bind="text: clientsListVal"></span>
<label for="members">Members</label>
<select id="members"
data-bind="ojComponent: {component: 'ojSelect',
options: memberList,
value: memberListVal,
rootAttributes: {style:'max-width:20em'}}">
</select>
</div>
</div>
</div>
Any help or hint? thank you!.
EDIT:
I think the problem is that self.clientsListVal is returning a function not the current selected value. I added console.log(self.clientsListVal) to the view model to see the current value.
If I change self.clientsListVal for a string:
if(this.id === 'C01'){}
I get the members of the client "C01".
I tried changing self.clientsListVal to $('#clients').val(), this is the id of the select input and i get undefined in the console.log.
How can I get the select field string value inside the viewmodel?
In Knockout, observables are functions -- so when you ask for the observable directly, like self.clientsListVal, you get the function definition. To get the underlying value, call the observable like a function: self.clientsListVal().
So your test becomes if (this.id === self.clientsListVal() ) {
Now you have another problem -- the observable holds an array, not an ID. The array may have a single ID element in it, but you have to reach into the array to get it.
Since you didn't show us how a value gets into clientsListVal, it's hard to say what you need to do. Is it bound to an input field where the user specifies a value? Is it populated from a data call? either way, do you ever need to have more than one ID in clientsListVal? If you only need to hold one ID at a time, change clientsListVal from an observableArray to a simple observable and your test will work.
If clientsListVal can hold multiple values, you'll need to loop over them. There are various ways to do this. You can get the underlying array by assigning the value of the observableArray to a variable: var clients = clientsListVal(). clients now holds the array, and you can use jQuery's $.each, the native Array.each, or some other way to loop over or map the array. Or you can use Knockout's built-in array utilities, like arrayForEach
if you don't want to change to a regular observable but expect the array to only have a single element, you can get at it like clientsListVal()[0] -- that's the 0th (first) element of the array. Watch out for empty arrays, tho.

Radio button not working within nested ng-repeats

I have a web page with check boxes & radio buttons within nested ng-repeats. When I am clicking the check boxes the underlying view model is getting updated properly, but when I click on the radio buttons, the view model is not getting updated properly. Within a group, when I select an option the selected model property gets updated to true but the other one doesn't change to false.
e.g. when I click on the radio buttons against chicken one by one, all of them becomes true. When I select any one, I want the other ones to become false
My view model is given below.
$scope.itemGroups = [{
"name": 'Non Veg',
"items": [{
"selected": false,
"name": 'Chicken',
"Portions": [{
"selected": false,
"name": '1 Cup'
}, {
"selected": false,
"name": '2 Cups'
}, {
"selected": false,
"name": '3 cups'
}]
}, {
"selected": true,
"name": 'Egg',
"Portions": [{
"selected": false,
"name": '1 Cup'
}, {
"selected": false,
"name": '2 Cups'
}, {
"selected": false,
"name": '3 cups'
}]
}]
}, {
"name": 'Veggie',
"items": [{
"selected": false,
"name": 'Potato',
"Portions": [{
"selected": false,
"name": '1 Cup'
}, {
"selected": false,
"name": '2 Cups'
}, {
"selected": false,
"name": '3 cups'
}]
}, {
"selected": false,
"name": 'Tomato',
"Portions": [{
"selected": false,
"name": '1 Cup'
}, {
"selected": false,
"name": '2 Cups'
}, {
"selected": false,
"name": '3 cups'
}]
}]
}];
The way I bind to the html:
<div ng-repeat="itemGrp in itemGroups">
<h1>{{itemGrp.name}}</h1>
<div ng-repeat="item in itemGrp.items">
<input type="checkbox" ng-model="item.selected" />{{item.name}}
<label ng-repeat="portion in item.Portions">{{portion.name}}
<input type="radio" name="radio_{{itemGrp.name}}" ng-model="portion.selected" ng-value="true" />
</label>
</div>
</div>
Fiddle: http://jsfiddle.net/awqv0rb0/16/
Can you please guide me on what can be the issue here? Is there a better way of achieving what I am trying to do here? I need to loop through the JSON and get the values of the selected items.
This is a trivial issue. I too, faced it an earlier stages.
If you are looping over a group of items and each item has a set of radio buttons, then all the radio buttons for a given item must have the 'name' attribute value as the item name.
Ex. If the item name is 'Chicken', all it's radio buttons labelled as '1 Cup', '2 Cups', '3 Cups' should have their name='{{item.name}}' i.e. 'Chicken'.
Change Point in your Code:
<input type="radio" name="{{item.name}}" ng-model="portion.selected" ng-value="true" />
Here is the JSFiddle demo
The code you have posted here doesn't quite match the fiddle you provided, but your issue is the result of giving each radio button it's own name, and therefore, it's own group. This allows all radio buttons to essentially function as check boxes and all be set to true instead of the desired behavior of allowing only one.
Instead, you should give all radio buttons under that item the same group name, like:
name="{{item.name}}"
Your nested ng-repeats should look something like this when you're done:
<div ng-repeat="item in itemGrp.items">
<input type="checkbox" ng-model="item.selected" />{{item.name}}
<label ng-repeat="portion in item.Portions">{{portion.name}}
<input type="radio" name="{{item.name}}" ng-model="portion.selected" ng-value="true" />
</label>
</div>
Updated per your Comment
To update the selected:true value of each of your portions when you change one, you'll need a little bit more code. This is a little messy, so it may not be the best solution--but I was able to get it to work.
In addition to the ng-value="true" you should also add an ng-change="toggleRadio(itemGrp,item,portion)"to your radio buttons. In your js, you should add the following function:
$scope.toggleRadio = function(itemGrp, item, obj) {
var indexOfItemGrp = $scope.itemGroups.indexOf(itemGrp);
var indexOfItem = $scope.itemGroups[indexOfItemGrp].items.indexOf(item);
var indexOfPortion = $scope.itemGroups[indexOfItemGrp].items[indexOfItem].Portions.indexOf(obj);
angular.forEach($scope.itemGroups[indexOfItemGrp].items[indexOfItem].Portions, function(value,key) {
if(indexOfPortion != key) {
value.selected = false;
}
});
};
Basically, this code will iterate through all of the portion options inside the item inside the itemGroup and update their value to false unless they were the selected option.
You can see a working example in a fork of your original fiddle that I created: here.
One More Update
Have a look at this question: AngularJS Binding Radio Buttons To Booleans Across Multiple Objects. If you can change the model of your json object, this might be a viable solution. If you can't change the model, manually updating the other values is your cleanest option.

Dynamic index in ng-repeat value

I have a simple ng-repeat iterating through an array of objects.
The ng-repeat contains a ng-model input element for which I need to use a dynamic value as the array index. Probably very unclear explanation so here is the code :
<div ng-repeat="property in current_data.object_subtype.object_property_type" ng-init="set_input_state()" class="input-group ng-scope disabled">
<span class="input-group-addon">{{property.name}}</span>
<input type="text" placeholder="{{property.name}}" ng-model="current_data.properties[getIndexFromId(current_data.properties, property.object_property_type_id)].value" class="form-control" disabled="disabled">
The problem is that the input stays empty. I've tested some combinations and found this to work :
getIndexFromId(current_data.properties, property.object_property_type_id) == 0
current_data.properties[0].value gives the expected output
So somehow getIndexFromId(current_data.properties, property.object_property_type_id)is not well accepted by Angular or I made a stupid mistake somewhere ...
Does anyone know what's wrong with this?
Thanks!
[edit]
Here is a sample of the data behind all this :
{
"id": 1,
"name": "Robert Smith",
"object_subtype_id": 1,
"object_subtype": {
"id": 1,
"description": "Manager",
"object_property_type": [
{
"id": 1,
"description": "Phone number"
},
{
"id": 2,
"description": "Hair color"
},
{
"id": 3,
"description": "Nickname"
}
]
},
"properties": [
{
"id": 1,
"value": "819-583-4855",
"object_property_type_id": 1
},
{
"id": 2,
"value": "Mauves",
"object_property_type_id": 2
},
{
"id": 3,
"value": "Bob",
"object_property_type_id": 3
}
]
}
From what I've seen of Angular, the content of the attributes are not executed as javascript. It's a custom parsed and executed mini-language that doesn't support complex indexing.
With that said, its probably for the best. Any sufficiently complex logic should be handled by the controller or a service.
function MyController($scope) {
$scope.set_current_data_value = function (current_data, property) {
var index = $scope.getIndexFromId(current_data.properties, property.object_property_type_id);
current_data.properties[index].value = $scope.property_name;
}
}
Then your html would look something like:
<input type="text" placeholder="{{property.name}}" ng-model="property_name" ng-change="set_current_data_value(current_data, property)" class="form-control" disabled="disabled">
You may also be able to use ng-submit if you don't need to update your model in real time.

Categories

Resources