I have a multi-select that I made with angular-ui.
I want to add an input that user can change the JSON key names so for example if the API that user add doesn't have "name" instead has "firstName" as the "key name" the app changes that and can work fine.
how can I get this result?
appreciate any help.
my code is here
what I really want is this: I should add this multi-select as a widget to a software named bonita studio and it should have an option that user can choose any API that want to use and should have an input field that the user will choose which one of the API's key identifier to iterate. for example if instead of name the user wants to iterate over the email s/he should be able to do.
I hope this explanation is enough
"use strict";
var app = angular.module("myApp", ['ui.select', 'ngSanitize']);
app.controller("myCtrl", function($scope, $http) {
$scope.headers = "";
var counter = 0;
var chunks = 5;
$scope.datas = [];
$scope.getData = function getData() {
return $http({
method: "GET",
url: "data.json"
})
.then(function onSuccess(response) {
for (let i = 0; i < response.data.length; i++) {
$scope.datas.push(response.data[i]);
}
//counter += chunks;
})
.catch(function onError(response) {
console.log(response.status);
});
}
/*$scope.loadMore = function () {
$http({
method: "GET",
url: "data.json"
})
.then(function loadMoreSuccess(response) {
for (let i = counter; i < (counter + chunks); i++) {
$scope.datas.push(response.data[i]);
}
counter += chunks;
})
.catch(function onError(response) {
console.log(response.status);
});
};*/
$scope.selected = {
value: $scope.datas[0]
};
});
#widgetContainer {
width: 100%;
}
ul li {
list-style: none;
text-align: center;
}
ul {
height: 120px;
overflow-y: auto;
}
#loadMore {
text-align: center;
color: #aaa;
background: #ddd;
cursor: pointer;
}
#category {
text-align: center;
background: #ddd;
}
#listContainer {
width: 20%;
}
span {
cursor: pointer;
}
h4 {
background: #ddd;
color: #aaa;
}
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="script/lib/angular/angular.js"></script>
<script src="https://code.angularjs.org/1.6.10/angular-sanitize.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-select/0.20.0/select.min.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-select/0.20.0/select.min.css">
<link rel="stylesheet" href="stylesheet/style.css">
</head>
<body ng-controller="myCtrl">
<div class="container">
<input type="text" ng-model="headers">
<ui-select multiple spinner-enabled="true" close-on-select="false" ng-model="selected.value">
<ui-select-no-choice>
couldn't find anything...
</ui-select-no-choice>
<ui-select-match placeholder="Select country...">
<span>{{$item.name}}</span>
</ui-select-match>
<ui-select-choices group-by="'category'" repeat="data in (datas | filter: $select.search) track by $index" refresh="getData($select.search)" refresh-delay="0">
<span>{{data.name}}</span>
</ui-select-choices>
</ui-select>
</div>
<script src="script/script.js"></script>
</body>
</html>
// Supose you have an object with desired change relations:
var relations = { firstName: "name", oldKey: "newKey" };
// Also, you have your dataArray:
var dataArray = [
{ firstName: "foo", oldKey: 1 },
{ firstName: "bar", oldKey: 2 }
];
// Here follows how you can switch keys:
Object.entries(relations).map(([oldKey, newKey]) => {
dataArray.map(data => {
data[newKey] = data[oldKey];
delete data[oldKey];
})
});
// Check out the result:
console.log(dataArray);
Loop over it and create a new key name then delete the old one like :
jsonData.forEach((data)=>{
data.name = data.firstName;
delete data.firstName;
})
Related
I'm working on a Javascript function that will set a kendo.data.HierarchicalDataSource object using a url that fetches the data. At the end of this function, if the data source actually has data, I want to set a treeview with the data (which is already working). If it doesn't have data, instead of setting the treeview, I want to make a label visible that tells the user that there is no data.
My problem: How to I determine that there is/isn't data in the HierarchicalDataSource? When I try call any function or get any property of getData, it returns undefined.
function loadTreeGroupData(applicationId) {
var treeview = $("#treeview-kendo").data("kendoTreeView");
var url = $('#urlHolders').data("gettreeUrl");
var appId = 0;
if (applicationId != undefined && applicationId != "")
appId = applicationId;
var getData = new kendo.data.HierarchicalDataSource({
change: function (e) {
for (var i = 0; i < e.items.length; i++) {
e.items[i].load();
}
},
transport: {
read: {
url: url, //"GetAlertsTree",
dataType: "json",
contentType: "application/json",
data: { applicationId: appId }
}
},
schema: {
model: {
id: "id",
hasChildren: "hasChildren",
children: "measureGroups"
}
}
});
if (/*the treeview has data*/) {
treeview.setDataSource(getData);
} else {
/*set a label that tells the user that there's no data*/
}
}
I would suggest you to do the following changes in your code:
Set the HierarchycalDataSource at the treeView initialization, instead of add it later;
Declare treeView's div and label as display:none or whatever the way you hide them;
Use DataSource's requestEnd event to show/hide the elements.
<!DOCTYPE html>
<html>
<head>
<base href="https://demos.telerik.com/kendo-ui/treeview/remote-data-binding">
<style>html { font-size: 14px; font-family: Arial, Helvetica, sans-serif; }</style>
<title></title>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2021.2.616/styles/kendo.default-v2.min.css" />
<script src="https://kendo.cdn.telerik.com/2021.2.616/js/jquery.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2021.2.616/js/kendo.all.min.js"></script>
</head>
<body>
<div id="example">
<div class="demo-section k-content">
<div id="treeview" style="display: none"></div>
<div id="no-data-label" style="display: none">No data found</div>
</div>
<script>
var serviceRoot = "https://demos.telerik.com/kendo-ui/service";
homogeneous = new kendo.data.HierarchicalDataSource({
transport: {
read: {
url: serviceRoot + "/Employees",
dataType: "jsonp"
}
},
schema: {
model: {
id: "EmployeeId",
hasChildren: "HasEmployees"
}
},
requestEnd: (e) => {
if (e.response && e.response.length) {
$("#treeview").show();
$("#no-data-label").hide();
}
else {
$("#treeview").hide();
$("#no-data-label").show();
}
}
});
$("#treeview").kendoTreeView({
dataSource: homogeneous,
dataTextField: "FullName"
});
</script>
</div>
</body>
</html>
Dojo
I'm trying to create an upload webpage to put csv files in a S3 bucket.
I followed the tutorial from their website. https://aws.amazon.com/blogs/compute/uploading-to-amazon-s3-directly-from-a-web-or-mobile-application/
I modified the method to accept parameter filename. Everything works fine but can't find the way to upload file from html to S3.
I'm usual a backend pythonist and google to change this webpage/js, but I didn't manage to solve it.
I tried to change from reader.readAsDataURL(file) to reader.readAsText(file, 'UTF-8'), also data:image/jpg to data:text/csv or text/plain but on line that requires "includes" returns "length: false"
console.log('length: ', e.target.result.includes('data:image/jpeg'))
Down you can find my new code, if you can redirect me to some clues of how can I send csv file and also "?filename=original filename" in API, I'll really love you :).
<!DOCTYPE html>
<html>
<head>
<title>Upload file to S3</title>
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/axios#0.2.1/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<h1>S3 Uploader Test</h1>
<div v-if="!file">
<h2>Select a file</h2>
<input type="file" #change="onFileChange">
</div>
<div v-else>
<img :src="file" />
<button v-if="!uploadURL" #click="removeFile">Remove file</button>
<button v-if="!uploadURL" #click="uploadFile">Upload file</button>
</div>
<h2 v-if="uploadURL">Success! File uploaded to bucket.</h2>
</div>
<script>
const MAX_FILE_SIZE = 1000000
/* ENTER YOUR ENDPOINT HERE */
const API_ENDPOINT = 'https://<smth>.execute-api.eu-central-1.amazonaws.com/uploads'
// e.g. https://ab1234ab123.execute-api.us-east-1.amazonaws.com/uploads
new Vue({
el: "#app",
data: {
file: '',
uploadURL: ''
},
methods: {
onFileChange (e) {
let files = e.target.files || e.dataTransfer.files
if (!files.length) return
this.createFile(files[0])
},
createFile (file) {
// var image = new Image()
let reader = new FileReader()
reader.readAsText(file, 'UTF-8');
reader.onload = (e) => {
//console.log(e.target.result)
console.log('length: ', e.target.result.includes('data:/csv'))
if (!e.target.result.includes('data:text/csv')) {
return alert('Wrong file type', e.target.result)
}
if (e.target.result.length > MAX_FILE_SIZE) {
return alert('File is loo large.')
}
this.file = e.target.result
}
// reader.readAsDataURL(file)
},
removeFile: function (e) {
console.log('Remove clicked')
this.file = ''
},
uploadFile: async function (e) {
console.log('Upload clicked')
// Get the presigned URL
const response = await axios({
method: 'GET',
url: API_ENDPOINT+'?filename='+'last.csv'
})
console.log('Response: ', response)
console.log('Uploading: ', this.file)
let binary = atob(this.file.split(',')[1])
let array = []
for (var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i))
}
let blobData = new Blob([new Uint8Array(array)], {type: 'text/csv'})
console.log('Uploading to: ', response.uploadURL)
const result = await fetch(response.uploadURL, {
method: 'PUT',
body: blobData
})
console.log('Result: ', result)
// Final URL for the user doesn't need the query string params
this.uploadURL = response.uploadURL.split('?')[0]
}
}
})
</script>
<style type="text/css">
body {
background: #20262E;
padding: 20px;
font-family: sans-serif;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
text-align: center;
}
#logo {
width: 100px;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
h1, h2 {
font-weight: normal;
margin-bottom: 15px;
}
a {
color: #42b983;
}
img {
width: 30%;
margin: auto;
display: block;
margin-bottom: 10px;
}
</style>
</body>
</html>
As you are creating a static web site that uses script tags, consider using the AWS SDK for JavaScript to place objects into an Amazon S3 bucket. Uploading objects is covered in the AWS Developer Guide for JavaScript SDK Version 3.
Uploading photos to Amazon S3 from a browser
(Of course for your use case, replace photo files with a CSV file).
Thanks #smac2020 for direction, still pretty useful I didn't have the chance to study it more.
After few hours of vue.js learning, made this working code.
<!DOCTYPE html>
<html>
<head>
<title>Upload file to S3</title>
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/axios#0.2.1/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<h1>S3 Uploader Test</h1>
<div v-if="!file">
<h2>Select a file</h2>
<input type="file" #change="onFileChange">
</div>
<div v-else>
<div>File {{ name }} loaded </div>
<button v-if="!uploadURL" #click="removeFile">Remove file</button>
<button v-if="!uploadURL" #click="uploadFile">Upload file</button>
</div>
<h2 v-if="uploadURL">Success! File uploaded to bucket.</h2>
</div>
<script>
const MAX_FILE_SIZE = 1000000
/* ENTER YOUR ENDPOINT HERE */
const API_ENDPOINT = 'https://<smth>.execute-api.eu-central-1.amazonaws.com/uploads'
// e.g. https://ab1234ab123.execute-api.us-east-1.amazonaws.com/uploads
new Vue({
el: "#app",
data: {
file: '',
uploadURL: '',
name: ''
},
methods: {
onFileChange (e) {
let files = e.target.files || e.dataTransfer.files
if (!files.length) return
this.createFile(files[0])
},
createFile (file) {
let reader = new FileReader()
this.name = file.name
console.log(this.name)
reader.readAsText(file, 'UTF-8');
reader.onload = (e) => {
if (e.target.result.length > MAX_FILE_SIZE) {
return alert('File is loo large.')
}
this.file = e.target.result
}
},
removeFile: function (e) {
console.log('Remove clicked')
this.file = ''
},
uploadFile: async function (e) {
console.log('Upload clicked', this.name)
// Get the presigned URL
const response = await axios({
method: 'GET',
url: API_ENDPOINT+'?filename='+this.name
})
console.log('Response: ', response)
let blobData = new Blob([this.file], {type: 'text/csv'})
console.log('Uploading to: ', response.uploadURL)
const result = await fetch(response.uploadURL, {
method: 'PUT',
body: blobData
})
console.log('Result: ', result)
// Final URL for the user doesn't need the query string params
this.uploadURL = response.uploadURL.split('?')[0]
}
}
})
</script>
<style type="text/css">
body {
background: #20262E;
padding: 20px;
font-family: sans-serif;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
text-align: center;
}
#logo {
width: 100px;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
h1, h2 {
font-weight: normal;
margin-bottom: 15px;
}
a {
color: #42b983;
}
img {
width: 30%;
margin: auto;
display: block;
margin-bottom: 10px;
}
</style>
</body>
</html>
Angular js filter Working Fine But Throwing Itteration Errors
var app = angular.module('NGapp', []);
app.filter('altDate', altDate);
app.controller('MainCtrl', MainCtrl)
function MainCtrl($scope) {
$scope.data = {
'listProductCost': [{
'data': 1
}, {
'data': 23
}, {
'data': 234
}, ]
}
}
function altDate(_) {
return function(value) {
console.log(value)
if (!value || value.length === 0) {
return [];
} else {
var f = []
angular.forEach(value, function(data) {
f.push(data['data']);
})
var s = []
s.push({
'min': _.min(f),
'max': _.max(f)
})
return s;
}
//return s;
};
}
app.factory('_', LodashFactory);
/** #ngInject */
function LodashFactory($window) {
return $window._;
}
<!DOCTYPE html>
<html ng-app="NGapp">
<head>
<meta charset="utf-8" />
<title>AngularJS </title>
<link rel="stylesheet" href="style.css" />
<script data-require="lodash.js#4.17.4" data-semver="4.17.4" src="https://cdn.jsdelivr.net/npm/lodash#4.17.4/lodash.min.js"></script>
<script data-require="angular.js#1.5.x" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js" data-semver="1.5.11"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<md-card-content layout="row" layout-align="none" ng-repeat="datas in data.listProductCost | altDate ">
<div class="dark" flex="30">HO Cost</div>
<div>
<span>{{datas.min}}</span> % to <span>{{datas.max}}</span> %
</div>
</md-card-content>
</body>
</html>
Here is my Working Code With angularjs filter . the filter is working fine but iam getting itteration error in console
the purpose filter is to print only the minimum and maximum value of the discount. can anyone can resolve the issue or give me a idea to resolve this thanks in advance
I see you using lodash. Why not use _.minBy() instead of _.min() ?
That way you can reduce your altDate function to
altDate(_){
return function(value) {
return {
min: _.minBy(value, function(i) { return i.data }),
max: _.maxBy(value, function(i) { return i.data})
}
}
}
The ngTable document does not provide complete information and sample codes and hard to follow. I managed to make bellow code to fetch and display a table from server dynamically. But when I click the table header to sort, the getData (and so the $http) is triggered again, and the result is that after click, the column is not sorted, but the displayed data doubled itself horizontally (say, when open the page, the displayed columns are [id, name], after the click on a column of the table header, it becomes [id, name, id, name]).
<!DOCTYPE html>
<html>
<head lang="en">
<title><%= title %></title>
<meta charset="utf-8">
<script type="text/javascript" src="bower_components/angular/angular.min.js"></script>
<script type="text/javascript" src="bower_components/ng-table/ng-table.min.js"></script>
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="bower_components/ng-table/ng-table.min.css" />
<script>
(function () {
'use strict';
let app = angular.module('myApp', ['ngTable']);
app.controller('demoCtrl', ['$http', 'NgTableParams', function ($http, NgTableParams) {
let ctrl = this;
ctrl.cols = [];
ctrl.rows = [];
ctrl.tableParams = new NgTableParams({}, {
getData: function (params) {
ctrl.xhr = $http({
method: 'GET',
url: '/ng-table-demo/test_data',
}).then(function (rsp) {
let cols = Object.keys(rsp.data[0]);
for(let i = 0; i < cols.length; i++) {
ctrl.cols.push({field: cols[i], title: cols[i], sortable: cols[i], show: true});
}
ctrl.rows = rsp.data;
return ctrl.rows;
}, function (rsp) {
console.log('http failed.');
});
return ctrl.xhr;
}});
}]);
})();
(function () {
"use strict";
angular.module("myApp").run(configureDefaults);
configureDefaults.$inject = ["ngTableDefaults"];
function configureDefaults(ngTableDefaults) {
ngTableDefaults.params.count = 5;
ngTableDefaults.settings.counts = [];
}})();
</script>
</head>
<body>
<div ng-app="myApp" ng-controller="demoCtrl as ctrl" class="container-fluid">
<h2>ng-table-demo</h2>
<table ng-table-dynamic="ctrl.tableParams with ctrl.cols" class="table table-condensed table-bordered table-striped">
<tr ng-repeat="row in $data">
<td ng-repeat="col in $columns">{{row[col.field]}}</td>
</tr>
</table>
</div>
</body>
</html>
I tried to surround the ctrl.xhr block with bellow, then it stops to duplicate but the sort does not happen anyway.
if(ctrl.xhr === undefined) {
ctrl.xhr = $http...;
}
return ctrl.xhr;
What mistake(s) I made?
The workaround is abandon of getData and set the dataset on xhr succeeded. bellow code worked.
(function () {
'use strict';
let app = angular.module('myApp', ['ngTable']);
app.controller('demoCtrl', ['$http', 'NgTableParams', function ($http, NgTableParams) {
let ctrl = this;
ctrl.cols = [];
$http({
method: 'GET',
url: '/ng-table-demo/test_data',
}).then(function (rsp) {
let cols = Object.keys(rsp.data[0]);
for (let i = 0; i < cols.length; i++) {
ctrl.cols.push({
field: cols[i],
title: cols[i],
sortable: cols[i],
show: true
});
}
ctrl.tableParams = new NgTableParams({}, {
dataset: rsp.data
});
}, function (rsp) {
console.log('http failed.');
});
}]);
})();
Still, I don't know how getData works.
I am using ui-grid to bind data from Role Table which contains Department Id as PrimaryKey. I am calling Web Api to get all the roles in the table and show in ui-grid.
Department Table
Role Table
My real problem is that I want to convert Department Id to Department Name when it binds to grid using cellFilter and that is why I declare objMapping to map Department Id with Department Name. But every time when I run I see that cellFilter custom function i.e. 'mapDepartmentName' is getting called before objMapping is being set and also I am not able to refer objMapping in 'mapDepartmentName'.
My grid looks like this:-
However when I edit I get the result as below which is absolutely correct:-
My code snippet as below:-
var myApp = angular.module('appHome', ['ui.grid', 'ui.grid.edit']);
myApp.controller("ctrlRole", ['$scope', 'MetadataOrgFactory', function ($scope, MetadataOrgFactory) {
var arrDepts = [];
var objMapping = {};
MetadataOrgFactory.getApiCall('getpublisheddepts', function (dataSuccess) {
$scope.department = dataSuccess;
for (var cntElem = 0; cntElem < dataSuccess.length; cntElem++) {
var objDept = { id: dataSuccess[cntElem].DeptId, DeptId: dataSuccess[cntElem].DeptName }
arrDepts.push(objDept);
objMapping[dataSuccess[cntElem].DeptId] = dataSuccess[cntElem].DeptName;
}
$scope.gridRole.columnDefs[1].editDropdownOptionsArray = arrDepts;
}, function (dataError) {
});
$scope.gridRole = {
data: 'roleData',
columnDefs: [
{
field: 'RoleName', displayName: 'Role Name',
},
{
field: 'DeptId', displayName: 'Department Name',
editableCellTemplate: 'ui-grid/dropdownEditor',
cellFilter: 'mapDepartmentName:this',
editDropdownValueLabel: 'DeptId',
},
{
field: 'RoleDesc', displayName: 'About Role',
},
{
field: 'WorkingHrs', displayName: 'Working Hours',
},
{
field: 'RequestNumber', displayName: 'RequestNumber',
cellEditableCondition: true
}
]
}
MetadataOrgFactory.getApiCall('getallroles', function (dataSuccess) {
$scope.roleData = dataSuccess;
}, function (dataError) {
});
}])
.filter('mapDepartmentName', function () {
return function (input, scope) {
if (!input) {
return '';
} else {
return objMapping[input];
}
};
});
<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
.gridStyle {
border: 5px solid #d4d4d4;
height: 200px;
}
</style>
<meta charset="utf-8" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.min.js"></script>
<link rel="stylesheet" href="https://cdn.rawgit.com/angular-ui/bower-ui-grid/master/ui-grid.min.css" />
<script src="https://cdn.rawgit.com/angular-ui/bower-ui-grid/master/ui-grid.min.js"></script>
<script src="../Scripts/AngularControllers/RoleController.js"></script>
<script src="../Scripts/AngularServices/ApiCallService.js"></script>
</head>
<body ng-app="appHome">
<div ng-controller="ctrlRole">
<div class="gridStyle" ui-grid="gridRole" ui-grid-edit>
</div>
</div>
</body>
</html>
Call $scope.$apply() in getpublisheddepts at the end of factory callback.
as you didnt show ur factory I believe its doing something asynchronously which is not informing the view to reflect changes.
I stuck in the issue for long time.
I did the following change in the code and I am getting the results as well. Please let me know if this is the correct solution for this:-
MetadataOrgFactory.getApiCall('getpublisheddepts', function (dataSuccess) {
$scope.department = dataSuccess;
for (var cntElem = 0; cntElem < dataSuccess.length; cntElem++) {
var objDept = { id: dataSuccess[cntElem].DeptId, DeptId: dataSuccess[cntElem].DeptName }
arrDepts.push(objDept);
objMapping[dataSuccess[cntElem].DeptId] = dataSuccess[cntElem].DeptName;
}
$scope.deptmapping = objDeptMapping; //new code added here
$scope.gridRole.columnDefs[1].editDropdownOptionsArray = arrDepts;
}, function (dataError) {
});
Filter Class
.filter('mapDepartmentName', function () {
return function (input, scope) {
if (!input) {
return '';
} else {
return scope.grid.appScope.deptmapping[input]; //Change in code
}
};
});