Generating forms dynamically using json schema with angularjs - angularjs

I have a json schema which is something like below:
var schema = {
"type": "object",
"properties": {
"requestedFor": {
"type": "string"
},
"location": {
"type": "string"
},
"shortDescription":{
"type": "string"
},
"description": {
"type": "string"
}
}
};
var options = {
"fields": {
"requestedFor": {
"requestedFor": "text",
"label": "*Name"
},
"location": {
"type": "text",
"label": "*Location"
},
"shortDescription":{
"type": "text",
"label": "Short Description"
},
"description": {
"type": "textarea",
"label": "Description",
"rows": 5,
"cols": 60,
"label": "",
"wordlimit": 250
}
},
"form": {
"attributes": {
"method": "POST",
"action": "#",
"enctype": "multipart/form-data"
},
"buttons": {
"submit": {
"value": "Submit"
}
}
}
};
So i want to use this json schema to create a custom directive on the fly using angularjs. So for that i have created the code something like below:
var app = angular.module("app", [])
.directive("wrapper", function($compile, $interval) {
return {
scope: {
directiveName: "="
},
link: function(scope, elem, attrs) {
scope.$watch("directiveName", function() {
var html = "<" + scope.directiveName + "></" + scope.directiveName + ">";
elem.html(html);
$compile(elem.contents())(scope);
});
}
}
}).controller("addDirectives", function($scope, $interval) {
let directiveNames = ['d1', 'd2', 'd3', "d4"];
$scope.directiveName = directiveNames[0];
}).directive("d1", function() {
return {
template: "<input type='text'>Requested For</input>"
}
}).directive("d2", function() {
return {
template: "<input type='text'>Location</input>"
}
}).directive("d3", function() {
return {
template: "<input type='text'>Short Description</input>"
}
}).directive("d4", function(){
return {
template: "<input type='textarea'>Description</input>"
}
})
Here my intention is to use this json schema to generate the form dynamically because i have so many json files available so for that i need to create different custom directives.
<!DOCTYPE html>
<html ng-app="app">
<head>
<body ng-controller="addDirectives">
<div class="container">
<div class="row">
<div class="col-md-12">
<div id="form"></div>
</div>
</div>
</div>
</body>
</html>
So can anybody provide any solution for this?

Related

Loading json data into angularjs ng-repeat and outside of ng-repeat from same json file

i'm new to angular and a little lost. i'm able to load the data and display it, but i'm confused about loading other data that is not part of the ng-repeat i have set up from the same json file. here is what i have so far.
i would like to not use $scope.titleName = "John Doe"; $scope.infotext = "some more info" and have this info come from within the json file.
thanks for any help you can give.
var app = angular.module("myApp", []);
app.controller('something', function ($scope, $http){
$http.get('site.json').success(function(data) {
$scope.sites = data;
$scope.titleName = "John Doe";
$scope.infotext = "some more info"
});
});
/* json file content */
[
{
"name": "tim",
"image": "/features/home-1.jpg",
"link": "http://www.bbc.co.uk"
},
{
"name": "don",
"image": "/features/home-1.jpg",
"link": "http://www.bbc.co.uk"
},
{
"name": "Mike",
"image": "/features/home-1.jpg",
"link": "http://www.bbc.co.uk"
},
{
"sub": {"titleName": "Homer", "infotext":"two"}
}
]
<body ng-app="myApp" ng-controller="something" >
<div class="wrapper">
<h1>{{titleName}}</h1>
<p class="info">{{infotext}}</p>
<div class="big" ng-repeat="site in sites ">
<a href="{{site.link}}" target="_blank">
<img src="{{site.image}}">
</a>
<h2>{{site.name}}</h2>
</div>
</div>
</body>
Change your JSON because the last object of the array is different from sites, I suggest to have a JSON like this :
{
"sites": [{
"name": "tim",
"image": "/features/home-1.jpg",
"link": "http://www.bbc.co.uk"
}, {
"name": "don",
"image": "/features/home-1.jpg",
"link": "http://www.bbc.co.uk"
}, {
"name": "Mike",
"image": "/features/home-1.jpg",
"link": "http://www.bbc.co.uk"
}],
"sub": {
"titleName": "Homer",
"infotext": "two"
}
}
You have also to modify your controller
app.controller('something', function ($scope, $http){
$http.get('site.json').success(function(data) {
$scope.sites = data.sites;
$scope.titleName = data.sub.titleName;
$scope.infotext = data.sub.infotext;
});
});

Angular Schema Form not displayed

I am using angular-schema-form to display and validate a form.
I have this code in my controller:
MyApp.controller('formCtrl', ['$scope', '$rootScope','$state', '$http',
function ($scope, $rootScope, $state, $http) {
if (ENV != "dev") {
formData = localStorage.getItem("signup.v-1.0.0.json")
$scope.signupSchema=formData.schema;
$scope.signupForm=formData.form;
$scope.signupUser=formData.model;
} else {
// load the template and cache it
$http.get("/forms/signup.v-1.0.0.json")
.then(function (response) {
console.log(response);
// template loaded from the server
$scope.signupSchema = response.data.schema;
$scope.signupForm = response.data.form;
$scope.signupUser=response.data.model;
localStorage.setItem("signup.v-1.0.0.json", response.data);
});
}
}
]);
And this in signup-v-1.0.0.json:
{
"schema":{
"type": "object",
"title": "Comment",
"properties": {
"name": {
"title": "Name",
"type": "string"
},
"email": {
"title": "Email",
"type": "string",
"pattern": "^\\S+#\\S+$",
"description": "Email will be used for evil."
},
"comment": {
"title": "Comment",
"type": "string",
"maxLength": 20,
"validationMessage": "Don't be greedy!"
}
},
"required": [
"name",
"email",
"comment"
]
},
"form":
[
"name",
"email",
{
"key": "comment",
"type": "textarea",
"placeholder": "Make a comment"
},
{
"type": "submit",
"style": "btn-info",
"title": "OK"
}
],
"model":
{
}
}
In my view:
<div class="col-md-6">
<div class="featured-box featured-box-secundary default h420">
<div class="box-content" ng-controller="formCtrl">
<h4>Inscription</h4>
<p>Inscrivez vous en 2 minutes via ce formulaire.</p>
<form sf-schema="signupSchema" sf-form="signupForm" sf-model="signupUser"></form>
</div>
</div>
</div>
I'm passing the schemaForm module to my app :
MyApp = angular.module('MyApp', ['ui.router','pascalprecht.translate','ui.bootstrap','Facebook','googleplus','mgo-angular-wizard','ui','ngMaterial','ngAria','ngAnimate','schemaForm']);
Chrome does not display code, but I have no error messages.
I found the solution.
I need to broadcast 'schemaFormRedraw' to redraw the form in the ajax load result, or after data is retrieved in local storage:
$scope.$broadcast('schemaFormRedraw');

Watch variable outside angular change values and then update an angular function at the root scope

I have existing javascript code I need to wait to fire before calling my angular update function. Is it possible to observe changes to a variable outside an angular controller?
var myoutsidevariable = {};
// setup angular directives module
angular.module('scopeInheritance', []).controller('MyListCtrl', function ($scope) {
// basic initialization here for MyListCtrl controller
$scope.myList = [{ "Name": "ABC", "KEY": "1" },
{ "Name": "DEF", "KEY": "2" },
{ "Name": "GHI", "KEY": "3" },
{ "Name": "JKL", "KEY": "4" },
];
$scope.update = function (mynames) {
$scope.myList = JSON.stringify(mynames);
};
}) // now add directive to this
.directive('updateMyList', function () {
$watch(myoutsidevariable, function ($scope) {
$scope.update(myoutsidevariable); // try and update the list items
});
});
// myoutsidevariable changed...
function updatemyoutsidevariable() {
myoutsidevariable =
[{ "Name": "XYZ", "KEY": "8" },
{ "Name": "VWX", "KEY": "7" },
{ "Name": "STU", "KEY": "6" },
{ "Name": "PQR", "KEY": "5" },
];
}
updatemyoutsidevariable();
Html
<div ng-controller="MyListCtrl">
<ul class="menus">
<li class="menuitem" ng-repeat="item in myList" value="{{item.KEY}}">{{item.Name}}</li>
</ul>
</div>
It doesn't need JSON.stringify b/c its already a json object.

AngularJS conditionally add a custom 'data-toggle' attribute

I have the following directive:
myDirective.directive('sidebar', function () {
return {
restrict: 'E',
replace: true,
template: '<li ng-repeat="m in menu" ng-class="{\'dropdown\':m.submenu}">' +
'<a href="{{m.url}}" ng-class="{\'dropdown-toggle\':m.submenu}" ng-attr="{\'data-toggle=dropdown\': m.submenu">' +
'<i class="{{m.image}}"></i>' +
' {{m.name}}' +
'<b class="caret" ng-if="m.submenu"></b>' +
'</a>' +
'<ul ng-if="m.submenu" class="dropdown-menu">' +
'<li ng-repeat="s in m.submenu"><i class="{{s.image}}"></i> {{s.name}}</li>' +
'</ul>' +
'</li>',
link: function (scope, elem, attrs) {
scope.menu = [
{
"name": "Home",
"url": "/",
"image": "fa fa-bar-chart-o"
},
{
"name": "Data Integration",
"url": "/manage/dataintegration/index",
"image": "fa fa-dashboard"
},
{
"name": "Users",
"url": "/manage/users/index",
"image": "fa fa-dashboard"
},
{
"name": "Logger",
"url": "/manage/logger/index",
"image": "fa fa-dashboard"
},
{
"name": "Drop",
"url": "",
"image": "fa fa-dashboard",
"submenu": [
{
"name": "Logger",
"url": "/manage/logger/index",
"image": "fa fa-dashboard"
},
{
"name": "Logger2",
"url": "/manage/logger/index",
"image": "fa fa-dashboard"
}
]
}
]
}
}
});
I'm trying to get the data-toggle='dropdown' attribute to the a tag only if m.submenu exists using ng-attr but it doesn't work.
Assuming that's verbatim:
ng-attr="{\'data-toggle=dropdown\': m.submenu"
Is missing a closing }
As for me, ng-attr doesn't work at all, you can try this one
ng-attr-data-toggle="{{m.submenu && 'dropdown' || null}}"
but it will the attribute without the value even if m.submenu is false. Hope it will help.

How can I sort a directive output?

I have the following Directive:
app.directive('sidebar', function () {
return {
restrict: 'E',
replace: true,
template: '<li ng-repeat="(keymenu, valmenu) in menu"><i class="{{valmenu.image}}"></i><span class="hidden-sm">{{keymenu}}</span></li>',
link: function (scope, elem, attrs) {
scope.menu = {
"Home": {
"sort": 1,
"url": "/",
"image": "fa fa-bar-chart-o"
},
"Datasources": {
"sort": 2,
"url": "/datasources",
"image": "fa fa-dashboard"
},
"Logger": {
"sort": 3,
"url": "/Logger",
"image": "fa fa-dashboard"
}
}
}
}
});
Currently the order is: Datasources, Home, Logger I would like to order it either by the sort property or by it's 'natural' order as the elements are ordered within the scope.menu object.
You can use orderBy direcly into the <li /> template:
This code will sort your menu for the property name that you want:
'<li ng-repeat="(keymenu, valmenu) in menu| orderBy:myProperty">'
EDIT:
You should change the way your JSON looks, or you will have issues to access and order the menu. The way you did every menu entry is a different object, you should do like this:
scope.menu =[
{
"name": "Home",
"sort": 1,
"url": "/",
"image": "fa fa-bar-chart-o"
},
{
"name":"Datasources",
"sort": 2,
"url": "/datasources",
"image": "fa fa-dashboard"
},
{
"name": "Logger",
"sort": 3,
"url": "/Logger",
"image": "fa fa-dashboard"
}
]
Then sort by name for exemple:
'<li ng-repeat="(keymenu, valmenu) in menu| orderBy:name">'

Resources