how to convert data in a string using json in angular - json

I do not know exactly how I can bind my form data in JSON string. in my scenario, I use a string field in the database and have some checkbox fields that I have to save in only a single database column using JSON. for that, I created an HTML form, and I don't know how I can bind all data in a database. if someone knows then can guide me
documentList: [
{
'IsSpecifications': false,
'IsSpecificationscomment': ''
},
{
'IsDrawSchedule': false,
'IsDrawSchedulecomment': ''
},
{
'TqRfi': false,
'TqRficomment': ''
},
{
'InsEnqReqQouInfor': false,
'InsEnqReqQouInforcomment': ''
},
{
'PanEnqReqQouInfor': false,
'PanEnqReqQouInforcomment': ''
},
{
'PanSubContQuot': false,
'PanSubContQuotcomment': ''
},
{
'MccSchedule': false,
'MccScheduleComment': ''
},
{
'ScPackQuot': false,
'ScPackQuotComment': ''
},
{
'O3rdPartyQuot': false,
'O3rdPartyQuotcomment': ''
},
{
'EquipSchedule': false,
'EquipScheduleComment': ''
},
{
'PointSchedul': false,
'PointSchedulComment': ''
},
{
'ValveSchedul': false,
'ValveSchedulComment': ''
},
{
'IdentRiskOpport': false,
'IdentRiskOpportComment': ''
},
{
'InstSubContQuot': false,
'InstSubContQuotComment': ''
}
];
<div class="my-3">
<ejs-checkbox label="isSpecifications()" labelPosition="Before"></ejs-checkbox>
</div>
<div class="my-3">
<ejs-checkbox label="Drawings/Schedules" labelPosition="Before"></ejs-checkbox>
</div>
<div class="my-3">
<ejs-checkbox label="TQ’s / RFI’s" labelPosition="Before"></ejs-checkbox>
</div>
<div class="my-3">
<ejs-checkbox
label="Install Enquiry / request to quote information"
labelPosition="Before"
></ejs-checkbox>
</div>
<div class="my-3">
<ejs-checkbox
label="Panel Enquiry / request to quote information"
labelPosition="Before"
></ejs-checkbox>
</div>
<div class="my-3">
<ejs-checkbox label="Panel Sub Contractor Quotation" labelPosition="Before"></ejs-checkbox>
</div>
<div class="my-3">
<ejs-checkbox label="MCC Schedules" labelPosition="Before"></ejs-checkbox>
</div>
<div class="my-3">
<ejs-checkbox label="Other S/C Package Quotations" labelPosition="Before"></ejs-checkbox>
</div>
<div class="my-3">
<ejs-checkbox label="Other 3rd Party Quotations" labelPosition="Before"></ejs-checkbox>
</div>
<div class="my-3">
<ejs-checkbox label="Equipment Schedules" labelPosition="Before"></ejs-checkbox>
</div>
<div class="my-3">
<ejs-checkbox label="Points Schedules" labelPosition="Before"></ejs-checkbox>
</div>
<div class="my-3">
<ejs-checkbox label="Valve Schedules" labelPosition="Before"></ejs-checkbox>
</div>
<div class="my-3">
<ejs-checkbox
label="Identifed Risks and Opportunities (INCL. VALUE ENGINEERING)"
labelPosition="Before"
></ejs-checkbox>
</div>
<div class="my-3">
<ejs-checkbox label="Install Sub Contractor Quotation" labelPosition="Before"></ejs-checkbox>
</div>
in the database, I use documentlist field in that all my checkbox values save in JSON string.

I think what are you searching for is JSON.parse()
See documentation here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse?retiredLocale=it

Stackblitz
Main purpose of this answer is to provide the stackblitz. This is not a tutorial.
To fully understand the code requires learning:
Angular Reactive Forms (form group, form array etc.) - see https://angular.io/guide/reactive-forms
Some RxJS (delay, takeUntil(this.destroyed$) etc.) - see https://angular.io/guide/rx-library
Control Value Accessor (writeValue etc.) - a previous SO answer I gave or https://www.youtube.com/watch?v=kVbLSN0AW-Y
Note instead of Control Value Accessor you could pass in a form group as an input. This is partly a matter of preference.
Overview
Implementing the control value accessor on custom component ejs-checkbox means we can bind it via
<ejs-checkbox formControlName="{{ i }}"></ejs-checkbox>
and any changes will be reflected in the overall form group.
Make some changes to form and watch the valueChanges console logs to see this.
I've used a form array for the document list. This allows the size of the array to change. If this will not change you could replace with form controls.
I've provided an exampleSave() that converts the form group value to match your documentList. You could JSON.stringify this and send to server as described in your question.

Related

How to bind JSON object key value pair separately to angular template

And i have a dynamic json coming from an API as below:
{123: "Mumbai", 456: "Bangalore", 789: "Chennai", 101: "Andhra",...}
I have below HTML code written in my template in which I am getting image-1, image-2 logos from my assets folder
<div class="row">
<div class="col-6" (click)="cityClick('Bangalore')">
<div class="img-1">
// my image-1 logo goes here
</div>
<div class="img-text">
Bangalore
</div>
</div>
<div class="col-6" col-6 (click)="cityClick('Mumbai')">
<div id="image_block" class="img-2">
// my image-2 logo goes here
</div>
<div id="text_block" class="img-text">
Mumbai
</div>
</div>
</div>
How to get the key of the json when i click on image and also display the text below the image from the corresponding key-value.
And when i click i should be able to pass the key and text inside the click event. Please help as i am new to Angular!
First convert this JSON into an JavaScript/TypeScript array like below:
var json = {123: "Mumbai", 456: "Bangalore", 789: "Chennai", 101: "Andhra" };
var jsonToBeUsed = [];
for (var type in json) {
item = {};
item.key = type;
item.value = json[type];
jsonToBeUsed.push(item);
}
This will result in data like below:
Now use NgFor in the template to bind array. (Refer this for NgFor)
<div class="row">
<div *ngFor="let item of array">
<div class="col-6" (click)="cityClick(item)">
<div class="img-1">
// my image-1 logo goes here
</div>
<div class="img-text">
{{item.value}}
</div>
</div>
</div>
</div>
We have passed the whole object in the click event. You can read any of the desired property from the object in click event handler which you will write in the component.
For your special requirement, you can use below markup:
<div class='row' *ngFor='let index of array; let i = index; let even = even'>
<div *ngIf="even" class='col-6' (click)="cityClick(array[i])">
<div class="img-1">
// my image-1 logo goes here
</div>
<div class="img-text">
{{array[i].value}}
</div>
</div>
<div *ngIf="!even" class='col-6' (click)="cityClick(array[i])">
<div class="img-1">
// my image-1 logo goes here
</div>
<div class="img-text">
{{array[i].value}}
</div>
</div>
</div>
Use this below function in your code:
getKeyByValue(object, value) {
return Object.keys(object).find(key => object[key] === value);
}
And use as
var dynamicJson = {123: "Mumbai", 456: "Bangalore", 789: "Chennai", 101: "Andhra"}
cityClick(value){
var key = this.getKeyByValue(this.dynamicJson, value);
console.log(key);
}
{123: "Mumbai", 456: "Bangalore", 789: "Chennai", 101: "Andhra",...}
Do you have influence on that JSON? This highly looks like a design issue for me. I assume those numbers are id's. I believe somethings like this should be better:
[{id: "123", name: "Mumbai"}, {id: "456", name: "Bangalore"}, {id: "789", name: "Chennai"}, {id: "101", name: "Andhra"},...}]
In that case you receive an array of cities, which could be an interface to parse to.
export interface City {
id: string;
name: string;
}
And you can easily render it in html by using *ngFor
<div *ngFor="let city of cities">
<!--do something with city.id and city.name-->
</div>
<div *ngFor let value of json |keyvalue > </div>

passing html values to javascript functions

I have a ng-repeat in my view and I want to pass the object from my ng-repeat to a javascript function but when I try to display it on the console it gives me undefined.
Here is my html:
<!-- Panel -->
<div class="row">
<div class="col-lg-12">
<div class="panel panel-primary">
<div class="panel-heading">
{{card}}
</div>
<!-- /.panel-heading -->
<div class="panel-body">
<div id="nvd3-container" class="md-card" style="overflow-x: auto" ng-if="dataloaded0">
<md-card-content id="nvd3-scrollable-content" style="width: {{width}}px; height: 350px;">
<md-tabs md-dynamic-height="" md-border-bottom="">
<md-tab ng-repeat="pu in selectedKpi" label="{{pu.dprdProuNr}}">
<md-content class="md-padding">
<div class="row">
<div class="col-md-6">
{{pu.item1}}
{{pu.item2}}
</div>
</div>
</md-content>
</md-tab>
</md-tabs>
</md-card-content>
</div>
</div>
<!-- /.panel-body -->
<a href="" ng-click="footerLinkClicked(pu)">
<div class="panel-footer">
<span class="pull-left">Trend</span>
<span
class="pull-right">
<i class="fa fa-arrow-circle-right"></i>
</span>
<div class="clearfix"></div>
</div>
</a>
</div>
</div>
</div>
<!-- /.panel -->
Here is my js file that returns undefined:
angular.module('App')
.directive('KpiParameter', function() {
return {
restrict: 'E',
templateUrl: 'app/kpi/kpi-parameter/kpi-parameter.html',
scope: {
card: '=',
kpiParamCallback: '&',
selectedProductionUnit: '<'
},
controller: function($scope, $rootScope, KpiChartFactory, $filter) {
console.log("!???????");
console.log($scope.selectedProductionUnit);
$scope.$watch('selectedProductionUnit', function() {
console.log($scope.selectedProductionUnit);
console.log("Changed");
KpiParamUpdated();
$scope.kpiParamCallback({
selectedProductionUnit: $scope.productionUnitDefault
});
}, true);
function KpiParamUpdated() {
console.log("KPiParamUpdated");
console.log($scope.selectedProductionUnit);
$scope.dataloaded0 = true;
KpiChartFactory.get({ pu: $scope.selectedProductionUnit }, function(data) {
$scope.selectedKpi = data;
console.log($scope.selectedKpi);
$rootScope.$broadcast('kpiParams', $scope.selectedKpi);
});
}
$scope.footerLinkClicked = function(pu) {
console.log("parameters received :");
console.log(pu);
}
},
controllerAs: "KpiPCtrl"
};
});
Do you have any idea why? I need to define it also in my js file?
As found in the docs of AngularMaterial, you can only achieve what you want to do by using md-on-select
Attributes
Parameter Type Description
label string
Optional attribute to specify a simple string as the tab label
ng-disabled boolean If present and expression evaluates to truthy, disabled tab selection.
md-on-deselect expression Expression to be evaluated after the tab has been de-selected.
md-on-select expression Expression to be evaluated after the tab has been selected.
md-active boolean When true, sets the active tab. Note: There can only be one active tab at a time.
Note: This event differs slightly from ng-click, in that if a tab is already selected and then clicked, the event will not fire.
Your call to footerLinkClicked() has no way of knowing which pu to use unless you tell it which one to use. And since it's outside of your ng-repeat, there's no overly easy way to do that.
md-tabs has an attribute called md-selected that allows you to store the currently selected index in a variable. So assuming that selectedKpi is an array (or is array-like), you can do this:
<md-tabs md-dynamic-height="" md-border-bottom="" md-selected="selectedTab">
and this:
<a href="" ng-click="footerLinkClicked(selectedKpi[selectedTab])">
and you should be all set.

access certain element of JSON in angular JS

Below is my JSON file:
[
{
"Name":"Peter England Shirt",
"Prodimage":["./images/zoom/zoom1hi.jpg","./images/zoom/zoom2hi.jpg","./images/zoom/zoom3hi.jpg"],
"actualPrice":"90",
"discountedPrice":"70",
"desc":"Cotton",
"Prodcolor":["#f1f40e","#adadad","#4EC67F"],
"quantity":[1,3,4,5,60],
"size":["XL","L","M","S"],
"detail":"Take it away",
"sizeChart":["16 waist","Measurements taken from size 30","Model wears size 31. Model is 6'2"],
"shipping":[
{
"type":"Standard",
"days":"5-6 days",
"cost":"200"
},{
"type":"Next day",
"days":"1 days",
"cost":"500"
}
],
"sellerList":[
{
"sellerName":"ABC",
"price":"566",
"deliveryDay":"4-5 working days"
},{
"sellerName":"SEDF",
"price":"300",
"deliveryDay":"4-5 working days"
},{
"sellerName":"QWER",
"price":"555",
"deliveryDay":"2-5 working days"
}
]
}
]
The JS file is as below:
var pJson="./json/product.json";
$http.get(pJson).success(function(response){
$scope.product=response;});
Now, if I want to access "Name" attribute I can call {{product[0].Name}}.
But I am not able to access Prodimage attribute using ng-repeat. I am trying like this:
<div ng-repeat="image in product.Prodimage">
{{image[0]}}
</div>
is this wrong?>
Yes this is wrong ,, note that you have the product object as array ,, so if you want the first object you should do this
<div ng-repeat="image in product[0].Prodimage">
{{image[0]}}
</div>
or if you want to iterate over all the products ,, you need to make a nested ng-repeat
<div ng-repeat="p in product">
<div ng-repeat="image in p.Prodimage">
{{image[0]}}
</div>
</div>
You could loop over it, becasue the outside is technically an array, and use $first for you example of wanting to only grab the first image. You could also use $index but running it through a function that checks the $index.
Fiddle here http://jsfiddle.net/HB7LU/15324/
I just re worked it to loop twice like so
<div ng-repeat="prod in product">
<div ng-repeat="image in prod.Prodimage">
<div ng-show="$first">
{{image}}
</div>
</div>
</div>
then put a div inside the inner repeat that will only show if it's the first item. Again you could change that logic to show by index, or whatever you want. So if you know the index you could change that same logic to this -
see fiddle - http://jsfiddle.net/HB7LU/15332/
<div ng-show="checkIndex($index)"> << or whatever index you want
{{image}}
</div>
and in the controller
$scope.checkIndex = function(item){
if(item === 0){
return true;
}else{
return false;
}
}
You just pass the index of the current item in the repeat and check it. I would recommend this logic over the Prodimage[0] logic so you are not hardcoding it into the html, so if you have to change the desired index, you change it in the controller, not template. The checkIndex is a quick example, you could change that to do whatever you want.
$scope.product[n].Prodimage is an array. So, you need to loop through your product array first, and then loop through the Prodimage array of each product:
<div ng-repeat="prod in product">
<div ng-repeat="image in prod.Prodimage">
{{ image }}
</div>
</div>
Of course, you could also just access the nth image using something like:
<div ng-repeat="prod in product">
{{ prod.Prodimage[0] }}
</div>
Can you change your json to
"Prodimage":[
{ "loc": "./images/zoom/zoom1hi.jpg"},
{ "loc": "./images/zoom/zoom2hi.jpg"},
{ "loc": "./images/zoom/zoom3hi.jpg"}],
then your loop should work
<div ng-repeat="image in product.Prodimage">
{{image.loc}}
</div>

Nested ngrepeats with inconsistent data structures

I am creating a set of divs from a JSON object using ng-repeat that construct "note" cards. The number of cards is determined by the number of JSON objects in the array. "Type" designates the header of the card, and "Content" designates the body. However, the contents of "Content" is not consistent. In some examples, the content is merely a sentence or paragraph. In others, the content is an array. When the content is a sentence, the formatting is handled fine. When the content is an array, I end up with the actual array in text format [{"year":"2009", "operation":"caesarean"},{"year":"2010", "operation":"torn meniscus"}] as the body of the card. Any ideas of how to implement this without scripting each card individually?
HTML
<section name="patientinfo">
<div align="center" ng-controller="HistoryCtrl">
<div class="grid-container" ng-repeat="record in historyItems">
<div class="row" row>
<div class="col-2" ng-repeat="history in record.History">
<div class="note" draggable="true">
<div class="row" id="rowhead3">
<div class="col-6" >
<span class="note-header">{{history.type}}</span>
</div>
</div>
<div class="row">
<div class="col-6" style="overflow: auto; height:250px;">
<div>
<span class="note-content">
{{history.content}}
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
JSON Example (the actual JSON is huge). There are many other entries besides "history". Also, these notes are not from a real person, so don't worry.
"History": [
{
"type": "medical",
"content": [
{
"condition": "IBS"
},
{
"condition": "Torn Meniscus Right Knee"
},
{
"condition": "Seasonal Allergies"
}
]
},
{
"type": "SOCIAL HISTORY",
"content": "Lives with husband and 3 children. No history of violence, domestic violence, or rape. Feels safe at home and in relationship. ETOH on weekends (socially 4 drinks in one weekend occasionally) and occasionally smokes cigarettes and marijuana. Admits to very rare marijuana on special occasions."
}]
Example of what I'm ending up with:
http://i.stack.imgur.com/MtuBN.png
You should transform or augment the data into a new format where you have the following structure for each note:
{
type: "string",
contentType: "(text|list)",
content: "string" // OR array of strings
}
To do this, you will need to have custom logic to transform each object in the array to a single string.
Then just use an ng-switch on the contentType attribute to decide which markup to use (e.g. a <ul> if contentType is list).

Represent html from JSON array using ng-bind-html

I want to render HTML tags from a property of a JSON object and represent them in a modal.
I have this JSON object:
{
"fileUploadCategories": [
{
"id": "Bread",
"title": "GrandmaBread",
"info": "Some info text.",
"restService": "empty",
"detailedInfo": [ "<h1>Stedsnavn</h1>",
"",//line break
"<i>Some text on a new line.</i>",
"",//line break
"Some text on the next line again <b>Should be bold.</b>"]
},
{
"id": "Cake",
"title": "My Cake",
"info": "Info text blah.",
"restService": "empty",
"detailedInfo": "<b>Test</b> <br> This is a text on a new line <br> New line"
}
]
}
In my html i use angularjs with ng-repeat and ng-bind-html to bind the data to a bootstrap modal. Here is my code:
<div class="panel-group" id="accordion" ng-repeat="fileUpload in fileUploadConfig" >
<div class="panel panel-default" >
<div class="panel-heading">
<h3 class="panel-title">{{fileUpload.title}}</h3>
</div>
<div class="panel-body">
<p class="bg-info">{{fileUpload.info}}</p>
<div class="form-horizontal">
<button class="btn btn-primary" id="{{fileUpload.id}}HelpBox" style="float:right" data-toggle="modal" data-target="#{{fileUpload.id}}HelpModal">
Hjelp
</button>
</div>
</div>
</div>
<!-- Modal -->
<div id="{{fileUpload.id}}HelpModal"class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="myModalLabel">{{fileUpload.id}}Help</h4>
</div>
<div class="modal-body" ng-bind-html="fileUpload.detailedInfo">
{{fileUpload.detailedInfo.join('\n')}}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Lukk</button>
</div>
</div>
</div>
</div>
</div>
When I have my html text in an array it does not render as it is suppose to. (The first JSON object). It works fine in the second JSON object(just have to remove the .join('\n') ). The reason I have represented the HTML in an array is so that it will be easier to change the text later and see how it will render, instead out putting everything on a single line with html tags inside, which looks really messy.
Is there a better way than using an array to represent the data in the JSON object and get it to render the html tags?
I have created a sample for you in order to visualize what's going on. As you can see, applying angularjs markup to the array data type results in rendering "stringified" array:
<div>{{fields.test}}</div> => ["a","b","c"]
Now, I have big doubts that using an array is good idea at all. Semantically this is incorrect and is quite confusing. Just encode your html within the JSON and later decode it (known as sanitize in angular, see more here):
function MyControllerHtml($scope, $sce) {
$scope.renderHtml = function(value) {
return $sce.trustAsHtml(value);
};
$scope.html = '<h1>Stedsnavn</h1><br/><i>Some text on a new line.</i><br/>Some text on the next line again <b>Should be bold.</b>';
};
<div ng-controller="MyControllerHtml">
<div ng-bind-html="renderHtml(html)"></div>
</div>
Finally, if you still want to keep array, then use angular directive to bind your array into hml