Submit and edit value in the same form in AngularJS - json

I have just started using AngularJS.
I would like to send and edit value in the same form.
Here is my approach :
I fill the input with the scope array with ng-init.
And with the scope fields, I store the new value when I click on the button submit.
But it doesn't seem to work... I don't understand why.
index.html
<form class="form" name="myForm" novalidate>
<div class="col span12 input"><input type="text" ng-model="fields.name" ng-init="array.name" required /></div>
<div class="col span12 input"><input type="text" ng-model="fields.age" ng-init="array.age" required /></div>
<select ng-model="fields.po_id" ng-init="fields.po_id" ng-options="productOwner in productOwners" required></select>
ng
Add
</form>
controllers.js
$scope.productOwners =
[
{
"id": 1
},
{
"id": 2
},
{
"id": 3
},
{
"id": 4
},
];
$scope.array =
[
{
"name": "Hello"
},
{
"age": "18"
},
{
"po_id": "2"
}
];
$scope.submit = function(fields){
}

I've created a working Plunker solving your issue.
You had two issues in your code:
1) ng-init="array.age" should be ng-init="fields.age=array.age" and same thing for the other ng-init.
You wasn't saving the value in fields so it wasn't updated.
2) Your array definition was faulty.
You should either define array as:
$scope.array = {
"name": "Hello",
"age": "18"
};
Or change the call to array in the HTML template like that:
array.name -> array[0].name
array.age -> array[1].age
EDIT:
Updated Plunker
The correct use of ng-options is
for array data sources:
label for value in array
select as label for value in array
label group by group for value in array
select as label group by group for value in array
for object data sources:
label for (key , value) in object
select as label for (key , value) in object
label group by group for (key, value) in object
select as label group by group for (key, value) in object
So I've changed your ng-options from ng-options="productOwner in productOwners" to ng-options="productOwner.id for productOwner in productOwners" which is of the type : label for value in array where the label is productOwner.id and the value is the object productOwner.
Moreover, the ng-init is not needed since fields.po_id has no value at the initialization.
But if you want to initialize the value, you can do something like :
ng-init ="fields.po_id = productOwners[0]"

Related

Ng-Zorro select not showing selected items with NgModel

I am using Ng-Zorro's multiple select, which is in a drawer. When opening the drawer, I give the select element a list of options and a list of items that are already chosen. The list of options to pick from works fine, but the already selected items do not show. This can be seen here as well: StackBlitz
The code:
<nz-select [(ngModel)]="selectedAttributes"
[nzMaxTagCount]="3"
[nzMaxTagPlaceholder]="attributeTagPlaceHolder"
nzMode="multiple"
name="changeAttributes"
id ="changeAttributes"
nzPlaceHolder="Please select">
<nz-option *ngFor="let attribute of allAttributes" [nzLabel]="attribute.name" [nzValue]="attribute"></nz-option>
</nz-select>
<ng-template #attributeTagPlaceHolder let-selectedList> "and " {{ selectedList.length }} " more items" </ng-template>
where the allAttributes list is formatted like this:
allAttributes= [
{
"id": 1,
"name": "Mask"
},
{
"id": 2,
"name": "Intensive"
},
{
"id": 3,
"name": "Family"
},
{
"id": 4,
"name": "Isolation"
}
];
and where the selectedAttributes is one or more of the items in the allAttributes list:
selectedAttributes= [{"id": 1,"name": "Mask"}];
No matter how I create or format the selected attributes list (it can be straight from the allAttributes list), the placeholder cannot be seen and the select is empty, plus when picking all options, the nzMaxTagPlaceholder shows there is an extra item picked.
Can anyone show me the way to set the selected items dynamically?
Try sth like below.
selectedAttributes = [this.allAttributes[0]];
Since
{"id": 1,"name": "Hapnikumask"}
is a complex object its equality will be checked by references. So you are defining a new object as selected it will be different from the source object.
use compareFn in your nz-select like this.
<nz-select
[(ngModel)]="selectedValue"
[compareWith]="compareFn"
(ngModelChange)="log($event)"
nzAllowClear
nzPlaceHolder="Choose"
>
in typescript file:-
compareFn = (o1: any, o2: any): boolean => (o1 && o2 ? o1.id === o2.id : o1 === o2);

how to extract properly when sqlite json has value as an array

I have a sqlite database and in one of the fields I have stored complete json object . I have to make some json select requests . If you see my json
the ALL key has value which is an array . We need to extract some data like all comments where "pod" field is fb . How to extract properly when sqlite json has value as an array ?
select json_extract(data,'$."json"') from datatable ; gives me entire thing . Then I do
select json_extract(data,'$."json"[0]') but i dont want to do it manually . i want to iterate .
kindly suggest some source where i can study and work on it .
MY JSON
{
"ALL": [{
"comments": "your site is awesome",
"pod": "passcode",
"originalDirectory": "case1"
},
{
"comments": "your channel is good",
"data": ["youTube"],
"pod": "library"
},
{
"comments": "you like everything",
"data": ["facebook"],
"pod": "fb"
},
{
"data": ["twitter"],
"pod": "tw",
"ALL": [{
"data": [{
"codeLevel": "3"
}],
"pod": "mo",
"pod2": "p"
}]
}
]
}
create table datatable ( path string , data json1 );
insert into datatable values("1" , json('<abovejson in a single line>'));
Simple List
Where your JSON represents a "simple" list of comments, you want something like:
select key, value
from datatable, json_each( datatable.data, '$.ALL' )
where json_extract( value, '$.pod' ) = 'fb' ;
which, using your sample data, returns:
2|{"comments":"you like everything","data":["facebook"],"pod":"fb"}
The use of json_each() returns a row for every element of the input JSON (datatable.data), starting at the path $.ALL (where $ is the top-level, and ALL is the name of your array: the path can be omitted if the top-level of the JSON object is required). In your case, this returns one row for each comment entry.
The fields of this row are documented at 4.13. The json_each() and json_tree() table-valued functions in the SQLite documentation: the two we're interested in are key (very roughly, the "row number") and value (the JSON for the current element). The latter will contain elements called comment and pod, etc..
Because we are only interested in elements where pod is equal to fb, we add a where clause, using json_extract() to get at pod (where $.pod is relative to value returned by the json_each function).
Nested List
If your JSON contains nested elements (something I didn't notice at first), then you need to use the json_tree() function instead of json_each(). Whereas the latter will only iterate over the immediate children of the node specified, json_tree() will descend recursively through all children from the node specified.
To give us some data to work with, I have augmented your test data with an extra element:
create table datatable ( path string , data json1 );
insert into datatable values("1" , json('
{
"ALL": [{
"comments": "your site is awesome",
"pod": "passcode",
"originalDirectory": "case1"
},
{
"comments": "your channel is good",
"data": ["youTube"],
"pod": "library"
},
{
"comments": "you like everything",
"data": ["facebook"],
"pod": "fb"
},
{
"data": ["twitter"],
"pod": "tw",
"ALL": [{
"data": [{
"codeLevel": "3"
}],
"pod": "mo",
"pod2": "p"
},
{
"comments": "inserted by TripeHound",
"data": ["facebook"],
"pod": "fb"
}]
}
]
}
'));
If we were to simply switch to using json_each(), then we see that a simple query (with no where clause) will return all elements of the source JSON:
select key, value
from datatable, json_tree( datatable.data, '$.ALL' ) limit 10 ;
ALL|[{"comments":"your site is awesome","pod":"passcode","originalDirectory":"case1"},{"comments":"your channel is good","data":["youTube"],"pod":"library"},{"comments":"you like everything","data":["facebook"],"pod":"fb"},{"data":["twitter"],"pod":"tw","ALL":[{"data":[{"codeLevel":"3"}],"pod":"mo","pod2":"p"},{"comments":"inserted by TripeHound","data":["facebook"],"pod":"fb"}]}]
0|{"comments":"your site is awesome","pod":"passcode","originalDirectory":"case1"}
comments|your site is awesome
pod|passcode
originalDirectory|case1
1|{"comments":"your channel is good","data":["youTube"],"pod":"library"}
comments|your channel is good
data|["youTube"]
0|youTube
pod|library
Because JSON objects are mixed in with simple values, we can no longer simply add where json_extract( value, '$.pod' ) = 'fb' because this produces errors when value does not represent an object. The simplest way around this is to look at the type values returned by json_each()/json_tree(): these will be the string object if the row represents a JSON object (see above documentation for other values).
Adding this to the where clause (and relying on "short-circuit evaluation" to prevent json_extract() being called on non-object rows), we get:
select key, value
from datatable, json_tree( datatable.data, '$.ALL' )
where type = 'object'
and json_extract( value, '$.pod' ) = 'fb' ;
which returns:
2|{"comments":"you like everything","data":["facebook"],"pod":"fb"}
1|{"comments":"inserted by TripeHound","data":["facebook"],"pod":"fb"}
If desired, we could use json_extract() to break apart the returned objects:
.mode column
.headers on
.width 30 15 5
select json_extract( value, '$.comments' ) as Comments,
json_extract( value, '$.data' ) as Data,
json_extract( value, '$.pod' ) as POD
from datatable, json_tree( datatable.data, '$.ALL' )
where type = 'object'
and json_extract( value, '$.pod' ) = 'fb' ;
Comments Data POD
------------------------------ --------------- -----
you like everything ["facebook"] fb
inserted by TripeHound ["facebook"] fb
Note: If your structure contained other objects, of different formats, it may not be sufficient to simply select for type = 'object': you may have to devise a more subtle filtering process.

Inserting Dynamic Data and Request Chaining Runscope

When the first step return a json object like this
{
"success":true,
"total":21,
"items":
[
{"id":"762"},
{"id":"763"},
{"id":"764"}
]
}
how can i assign variable id to the first "id" item in response
i have done it like this but it didn't work
i also tried items.id, items[0].id but that didn't work either
To assign a variable to an item in a list, you can use a post-response script.
In this case, something like:
var data = JSON.parse(response.body);
var myId = data.items[0].id;
variables.set("id", myId);

AngularJS: How to filter data by comparing the search text to only certain members of JSON object?

I want to filter a JSON based only certain members of the JSON object. Here is the fiddler and here is the html code.
<body ng-app="faq" ng-controller="faqDisplay">
<input ng-model="searchText"></input>
<div ng-repeat="question in questions|filter:searchText">
<li>{{question.question}}</li>
</div>
</body>
Here is the script for that
var faq = angular.module('faq', []);
faq.controller('faqDisplay', function ($scope) {
$scope.questions = [{
question: "Abc",
answer: "efg",
count: "197",
qname: "q1"
}, {
question: "FGH",
answer: "dfs",
count: "61",
qname: "q2"
}, {
question: "IJK",
answer: "dsds",
count: "3241",
qname: "q3"
}];
});
In my fiddle, if you enter in the values I have assigned for count or qname in the input field it will display the questions accordingly but I want it to filter only based on the data members: question and answer (Show the questions only if the searchText contains words/characters which are either in question or answer only).
Can anyone help me with this.
You can specify the property you want to filter upon
filter:{question:searchText}
Here is the fiddle
http://jsfiddle.net/knp4fyqq/2/
Here is full documentation
If you want to search on multiple properties, easiest would be to call a function on controller for filter.
For example, create a function in controller like this
$scope.search = function (row) {
return (row.question.toLowerCase().indexOf($scope.searchText.toLowerCase() || '') !== -1 || row.answer.toLowerCase().indexOf($scope.searchText.toLowerCase() || '') !== -1);
};
and update your filter in your binding like this
<body ng-app="faq" ng-controller="faqDisplay">
<input ng-model="searchText"></input>
<div ng-repeat="question in questions|filter:search">
<li>{{question.question}}</li>
</div>
</body>
And here is the fiddle
http://jsfiddle.net/knp4fyqq/7/

Prevent change of 'copied' object affecting original using ng-repeat in angular

I have a setup in angular which displays a json string called 'items'. Each item contains an array of field ids. By matching the field ids, it pulls information for the fields using a seperate 'fields' json string.
{
"data": [
{
"id": "1",
"title": "Item 1",
"fields": [
1,
1
]
},
{
"id": "2",
"title": "Item 2",
"fields": [
1,
3
]
},
{
"id": 3,
"title": "fsdfs"
}
]
}
You can copy or delete either the items or fields, which will modify the 'items' json.
Everything works except when I copy one item (and its fields), and then choose to delete a field for that specific item.
What happens is that it deletes the field for both the copied item AND the original.
Plunker -
http://plnkr.co/edit/hN8tQiBMBhQ1jwmPiZp3?p=preview
I've read that using 'track by' helps to index each item as unique and prevent duplicate keys, but this seems to be having no effect.
Any help appreciated, thanks
Edit -
Credit to Eric McCormick for this one, using angular.copy with array.push solved this issue.
Instead of -
$scope.copyItem = function (index) {
items.data.push({
id: $scope.items.data.length + 1,
title: items.data[index].title,
fields: items.data[index].fields
});
}
This worked -
$scope.copyItem = function (index) {
items.data.push(angular.copy(items.data[index]));
}
I recommend using angular.copy, which is a "deep copy" of the source object. This is a unique object from the source one.
It may seem slightly counter-intuitive, but a direct reference (as you're observing) interacts with the original object. If you inspect the element's scope after it's instantiated in the DOM, you can see there's a $id property assigned to the object in memory. Basically, by using angular.copy(source, destination), you ensure a copying of all the properties/values and having a unique object.
Example:
//inside the controller, a function to instantiate new copy of selected object
this.selectItem = function(item){
var copyOfItem = angular.copy(item);
//new item with same properties and values but unique object!
}
Egghead.io has a video on angular.copy.