I am working in an application where the user can provide a JSON formly form definition that is saved in the DB. Eventually, that definition will be used to generate a form.
I need to validate that JSON definition before saving it into the DB, something like what API-check does underneath.
Does angular-formly have something to do that or should I create my own validator?
Thanks.
Yes, you can see it at http://angular-formly.com/#/example/advanced/validators
Example with JSON:
{
"key": "test",
"className": "flex-gt-xs-100 flex",
"type": "input",
"templateOptions": {
"required": true
},
"validation": {
"messages": {
"required": "function(viewValue, modelValue, scope) {return scope.to.label + ' is required';}"
}
}
}
But JSON don't understand function. So, you need write code to do that
$http.get('test.json').success(function(array)
{
var jsonTransformed = JSON.parse(JSON.stringify(array), function (key, value) {
if (value && (typeof value === 'string') && value.indexOf("function") === 0) {
var jsFunc;
eval("jsFunc = " + value);
return jsFunc;
}
return value;
});
vm.fields = jsonTransformed;
});
You should write validate function in controller and declare it in formly-field
Related
I have a object called models.questions, I am using $watch to monitor its change(deep watch, monitoring the entire object of models.questions). Sth like:
$scope.$watch('models.questions', function (newVal, oldVal) {
do sth...
}
models.questions may contain data like this:
{
"Question": {
"Description": "",
"Index": "",
"QuestionType": "StaticElement",
"tag": "This is a static element",
"originalName": "Static - Label/Link/Image",
"Title": "",
"Required": true,
"Dynamic": "",
"Dependency": "",
"Hidden": false,
"Options": [],
"displayOptions": [
"x.png"
]
},
"Dependencies": {
"RelationBetweenOptions": "",
"Action": "",
"OptionsForSelect": [],
"DependencyOptions": []
}
}
My code works fine until recently. I need to put some File type object into "Options". I used to put string or int type into "Options", the code works.
But once I put a File type object into it. When the code executes $watch, I got error as
angular.js:14525 TypeError: Illegal invocation
at sa (angular.js:1205)
at sa (angular.js:1189)
at sa (angular.js:1205)
at sa (angular.js:1205)
at sa (angular.js:1189)
at m.$digest (angular.js:17993)
at m.$apply (angular.js:18269)
at angular.js:20186
at e (angular.js:6274)
at angular.js:6554
The file object is the file that user selected to upload. Sth like:
<md-input-container ng-if="item.Question.Required">
<button ngf-select ngf-change="upload($files,$index)" multiple="multiple">Add+</button>
</md-input-container>
The upload function as following:
$scope.upload = function (file, index) {
if ($scope.models.questions[index].Question.displayOptions === undefined) {
$scope.models.questions[index].Question.displayOptions = [];
}
for (var i = 0; i < file.length; i++) {
var count = 0;
var tmpFileName = file[i].name;
while ($scope.models.questions[index].Question.displayOptions.indexOf(tmpFileName) !== -1) {
tmpFileName = file[i].name + '(' + count + ')';
count++;
}
$scope.models.questions[index].Question.displayOptions.push(tmpFileName);
$scope.models.questions[index].Question.Options.push(file[i]);
}
};
I have no clue how to debug this. Does anyone know what causes this error?
Thank you.
I am having graph div. In that div i have given the referesh tool, and in the client controller I have to pass parametric function which will load data and then will remove the spinner
$scope.$on('panel-refresh', function(event, id) {
spinnerId=id;
// Instead of timeout you can request a chart data
$scope.loadChart(streamStats, cloudStats);
});
and this the funtion
function loadChart(streamStats, cloudStats)
{
streamStats.forEach(function (day)
{
var date = new Date(day._id);
date.setHours(0, 0);
streamSeries.push([date, day.count]);
});
cloudStats.forEach(function (day)
{
cloudSeries.push([new Date(day._id), day.count]);
});
$scope.splineData = [
{
"label": "Data Streams",
"color": "#564aa3",
"data": streamSeries
},
{
"label": "Cloud Syncs",
"color": "#2f80e7",
"data": cloudSeries
}
];
vm.splineData = $scope.splineData;
$scope.$broadcast('removeSpinner', spinnerId);
}
now problem is this that I am getting this error
angular.js:13236 ReferenceError: streamStats is not defined
at dashboard.controller.js:43
at Scope.$emit (angular.js:17070)
at HTMLAnchorElement.<anonymous> (panel-refresh.directive.js:42)
at HTMLAnchorElement.dispatch (jquery.js:4732)
at HTMLAnchorElement.elemData.handle (jquery.js:4544)
The below block is my JSON. The -KTYLrHDHt234rFDNHrm type hashes are generated by the supplied API of the client. I think they're using Firebase.
I am passing a query in the URL which contains the pageId for each of those nested objects.
Example https://cms.app.io/edit/Nike3243
But since the hash is auto generated how can I search through all the JSON and check if the pageId matches my Angular route and then only return the values of the same child.
{
"-KTYLrHDHtdq23423NHrm": {
"pageCreation": "10/8/2016, 14:14:22 PM",
"pageGallery": {
"slider_1_img": "http://",
"slider_2_img": "http://",
},
"pageId": "Nike13243",
"pageName": "Nike Campaign 1",
"store": "11"
},
"-KTYLrHDHtdqirFDNHrm": {
"pageCreation": "10/8/2016, 12:14:22 AM",
"pageGallery": {
"slider_1_img": "http://",
"slider_2_img": "http://",
},
"pageId": "Nike323243",
"pageName": "Nike Campaign 2",
"store": "12"
},
"-KTYLrHDHt234rFDNHrm": {
"pageCreation": "10/8/2016, 13:14:22 PM",
"pageGallery": {
"slider_1_img": "http://",
"slider_2_img": "http://",
},
"pageId": "Nike3243",
"pageName": "Nike Campaign 3",
"store": "13"
}
}
So I want to return only the data of Nike3243 but I want to return the store, the slider and the pageName. How can I do this since the KTYLrHDHt234rFDNHrm hash is something I will never know
cmsApp.controller('pages-edit', function ($scope, $http, $routeParams) {
var pageIdU = $routeParams.id;
$http.get(firebase_url+'cms/home.json'+randstatus).success(function(data) {
$scope.pages = data;
// this would be pageId = Nike3243
console.log(data.pageIdURI.pageName[pageId]);
});
});
Thanks
Assuming your object is called 'objTest', you could do something like this:
var strPageId = 'The page id to find', objFound;
for( var strKey in objTest ) {
var objTemp = objTest[strKey];
if ( objTemp['pageId'] == strPageId ) {
objFound = objTemp;
break;
}
}
if ( typeof objFound == "object" ) {
//Do something...object has been found!
}
I actually did this:
$.each(data, function (bb) {
var crossReference = data[bb].transId;
if (crossReference==pageIdUri) {
$scope.transNameEn = data[bb].transNameEn;
$scope.transNameArabic = data[bb].transNameArabic;
$scope.transCreation = data[bb].transCreation;
$scope.transModified = data[bb].transModified;
$scope.notes = data[bb].notes;
}
});
It may be easier for you to simply transform the data rather than perform this search over and over. You can loop through the data once and get it in the correct format.
I would do something like:
var recordLookup = {};
for (var id in records) {
var pageId = records[id].pageId;
recordLookup[pageId] = record[id];
recordLookup[pageId].originalId = id;
}
This way you can now easily look up any record by its page id. If you need to send the data back to the server in the original form you still have that original id and can do whatever you need to in order to get it in the proper format. This way you loop once or maybe twice, (once to make the lookup and once to revert at the end of your operation) rather than any time you need to get data out of your records.
I have a JSON response which contains an array of data.
$scope.Load = function () {
$http.post(elasticSearchURL, { "aggs": { "By_type": { "terms": { "field": "Name" }, "aggs": { "By_color": { "terms": { "field": "Color" } } } } } }).
then(function (response) {
$scope.modelList = response;
}, function (response) {
});
}
I would like to display the count of each element in the JSON.
MyHtml Code
<div ng-repeat="fruits in modelList.data.hits.hits | unique : '_source.fruitsName' | orderBy:'_source.fruitsName' ">
{fruits._source.name.length}
</div>
My Json data will be like this
{"_id":"e-AB2","_version":1,"found":true, "_source":{"name":"Apple", "color":"red"}}},
{"_id":"e-AB2","_version":1,"found":true, "_source":{"name":"Apple", "color":"red"}}},
{"_id":"e-AB2","_version":1,"found":true, "_source":{"name":"Apple", "color":"red"}}}
It displays only the length of the fruitname "Apple" length:5. I want to display the array length of _source.name
I have tried {{$index.length}} but it showing the count as 1 since I am using "unique:" in the <div>
How it can be achieved in angularjs.
Thanks in advance
I think the easiest approach is create hashmap that contains the counts:
$scope.counts = {};
$http.post(elasticSearchURL, postData).then(function (response) {
$scope.modelList = response.data;
response.data.forEach(function (item) {
var source = item._source.name;
if (!$scope.counts.hasOwnProperty(source)) {
$scope.counts[source] = 0;
}
$scope.counts[source]++;
});
});
Then in the view you can use:
Count = {{counts[fruits._source.name]}}
$scope.counts will look like:
{ 'Apple':3, 'Orange':5}
What you probably want to do is map all the data to a different array in this same fashion and get rid of the unique filter since there is no way to do what you are asking directly in the view
Suppose I have an array of objects like this:
$scope.data = [
{
"active": true,
"id": "4bcb19db-ec10-4de5-8ae6-b13388494651",
"name": "Owais Shah",
"username": "chekhov"
},
{
"active": false,
"id": "630d0582-1bf9-4331-9fa6-f6baa59319b2",
"name": "Tim Hunt",
"username": "one"
}
]
I can use this to deep watch the object:
$scope.$watch('data', function(){...}, true)
However, this is not efficient in my case, as the only property of these objects that I'm interest in watching is active.
Is there a way to watch only a specific property deep inside the object? Something like $scope.$watch('data[].active' ...)
I think you could do something like this:
for(var i=0,j=$scope.data.length;i<j;i++) {
$scope.$watch(data[i].active, function() { });
}
You can watch on a function which in turn returns your inner objects
$scope.$watch( function() {
return $scope.data.active[0];
},
function(newValue, oldValue) {
console.log('It changed!');
}
);
You can take advantage of the $watch function accepting a function and return a value you compute from the array. For example, you could look at it is a number based on the binary sequence of 0/1 for active = false or true. Something like this would work:
$scope.$watch(function() {
var value = 0, idx;
for (idx = 0; idx < $scope.data.length; idx += 1) {
value *= 2;
value += $scope.data[idx].active ? 1 : 0;
};
return value;
}, function() {
$scope.changes += 1;
$scope.status = "Changed " + $scope.changes + " times."; });
The jsFiddle here illustrates it: http://jsfiddle.net/jeremylikness/GrRtK/
You can see it illustrated by clicking the same button. The first time the element changes from true to false or vice versa, the change is registered, while subsequent updates do not trigger the watch. It will be even more readable if you use a mapping function from underscore to project the array onto your number or value to watch.