AngularJS - Upload Image to SharePoint Library/Corrupted File - angularjs

I am using the following Angular Module to attempt to upload images to SharePoint through a Web browser: https://github.com/nervgh/angular-file-upload
I am getting successful 200 POST messages and a file is being uploaded... However, it is not showing the image itself in the preview or opening of the image, but rather an [X]. I am guessing this is related to how the content is encoded, but unsure of what to do next. Here is my controller:
appControllers.controller('appUploadImageCtrl', ['$scope', '$location', 'FileUploader', function ($scope, $location, FileUploader) {
var uploader = $scope.uploader = new FileUploader({
url: "/sites/_api/web/lists/getByTitle('Images')/RootFolder/Files/add(url='test.jpg',overwrite='true')",
processData: false,
transformRequest: angular.identity,
headers: {
'Accept': 'application/json;odata=verbose', 'content-type': undefined, 'X-RequestDigest': $("#__REQUESTDIGEST").val() }
});
// FILTERS
uploader.filters.push({
name: 'imageFilter',
fn: function (item /*{File|FileLikeObject}*/, options) {
var type = '|' + item.type.slice(item.type.lastIndexOf('/') + 1) + '|';
return '|jpg|png|jpeg|bmp|gif|'.indexOf(type) !== -1;
}
});
// CALLBACKS
uploader.onWhenAddingFileFailed = function (item /*{File|FileLikeObject}*/, filter,
options) {
console.info('onWhenAddingFileFailed', item, filter, options);
};
uploader.onAfterAddingFile = function (fileItem) {
console.info('onAfterAddingFile', fileItem);
};
uploader.onAfterAddingAll = function (addedFileItems) {
console.info('onAfterAddingAll', addedFileItems);
};
uploader.onBeforeUploadItem = function (item) {
console.info('onBeforeUploadItem', item);
};
uploader.onProgressItem = function (fileItem, progress) {
console.info('onProgressItem', fileItem, progress);
};
uploader.onProgressAll = function (progress) {
console.info('onProgressAll', progress);
};
uploader.onSuccessItem = function (fileItem, response, status, headers) {
console.info('onSuccessItem', fileItem, response, status, headers);
};
uploader.onErrorItem = function (fileItem, response, status, headers) {
console.info('onErrorItem', fileItem, response, status, headers);
};
uploader.onCancelItem = function (fileItem, response, status, headers) {
console.info('onCancelItem', fileItem, response, status, headers);
};
uploader.onCompleteItem = function (fileItem, response, status, headers) {
console.info('onCompleteItem', fileItem, response, status, headers);
};
uploader.onCompleteAll = function () {
console.info('onCompleteAll');
};
console.info('uploader', uploader);
$scope.cancel = function () {
$location.path('/');
}
}]);
HTML:
<div class="col-md-3">
<h3>Select files</h3>
<div ng-show="uploader.isHTML5">
<!-- 3. nv-file-over uploader="link" over-class="className" -->
<div class="well my-drop-zone" nv-file-over="" uploader="uploader">
Base drop zone
</div>
<!-- Example: nv-file-drop="" uploader="{Object}" options="{Object}" filters="{String}" -->
<div nv-file-drop="" uploader="uploader" options="{ url: '/foo' }">
<div nv-file-over="" uploader="uploader" over-class="another-file-over-class" class="well my-drop-zone">
Another drop zone with its own settings
</div>
</div>
</div>
<!-- Example: nv-file-select="" uploader="{Object}" options="{Object}" filters="{String}" -->
Multiple
<input type="file" nv-file-select="" uploader="uploader" multiple /><br />
Single
<input type="file" nv-file-select="" uploader="uploader" />
</div>
<div class="col-md-9" style="margin-bottom: 40px">
<h3>Upload queue</h3>
<p>Queue length: {{ uploader.queue.length }}</p>
<table class="table">
<thead>
<tr>
<th width="50%">Name</th>
<th ng-show="uploader.isHTML5">Size</th>
<th ng-show="uploader.isHTML5">Progress</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in uploader.queue">
<td><strong>{{ item.file.name }}</strong></td>
<td ng-show="uploader.isHTML5" nowrap>{{ item.file.size/1024/1024|number:2 }} MB</td>
<td ng-show="uploader.isHTML5">
<div class="progress" style="margin-bottom: 0;">
<div class="progress-bar" role="progressbar" ng-style="{ 'width': item.progress + '%' }"></div>
</div>
</td>
<td class="text-center">
<span ng-show="item.isSuccess"><i class="glyphicon glyphicon-ok"></i></span>
<span ng-show="item.isCancel"><i class="glyphicon glyphicon-ban-circle"></i></span>
<span ng-show="item.isError"><i class="glyphicon glyphicon-remove"></i></span>
</td>
<td nowrap>
<button type="button" class="btn btn-success btn-xs" ng-click="item.upload()" ng-disabled="item.isReady || item.isUploading || item.isSuccess">
<span class="glyphicon glyphicon-upload"></span> Upload
</button>
<button type="button" class="btn btn-warning btn-xs" ng-click="item.cancel()" ng-disabled="!item.isUploading">
<span class="glyphicon glyphicon-ban-circle"></span> Cancel
</button>
<button type="button" class="btn btn-danger btn-xs" ng-click="item.remove()">
<span class="glyphicon glyphicon-trash"></span> Remove
</button>
</td>
</tr>
</tbody>
</table>
<div>
<div>
Queue progress:
<div class="progress" style="">
<div class="progress-bar" role="progressbar" ng-style="{ 'width': uploader.progress + '%' }"></div>
</div>
</div>
<button type="button" class="btn btn-success btn-s" ng-click="uploader.uploadAll()" ng-disabled="!uploader.getNotUploadedItems().length">
<span class="glyphicon glyphicon-upload"></span> Upload all
</button>
<button type="button" class="btn btn-warning btn-s" ng-click="uploader.cancelAll()" ng-disabled="!uploader.isUploading">
<span class="glyphicon glyphicon-ban-circle"></span> Cancel all
</button>
<button type="button" class="btn btn-danger btn-s" ng-click="uploader.clearQueue()" ng-disabled="!uploader.queue.length">
<span class="glyphicon glyphicon-trash"></span> Remove all
</button>
</div>
</div>

The problem with your code is that you are trying to upload your image as a normal byte array, which isn't possible when you are uploading to libraries through the SharePoint REST API.
To be able to upload non-text files to SharePoint, they have to be uploaded as a base64 encoded byte array.
Your options are to either use another Angular module such as Angular-Base64-Upload, or to encode the image file before you upload it using your first choice of file upload module.
In case you go for option two, you can encode the image using the following technique, though how it will work with your selected file uploader, I cannot say. It appears you can modify the file attribute of the FileItem in the file uploader, so it should not be that hard.
Encoding the image file to a base64 binary arraybuffer
//Create a new FileReader object
var reader = new FileReader();
reader.onload = processImage;
//Read the file as a base64 encoded string
reader.readAsDataURL(input.files[0]);
function processImage () {
//The image file has been read by the filereader
//and can be converted to an arraybuffer
var arrayBuffer = base64ToBinary(this.result);
//Upload the image to the SharePoint images library
uploadImage(arrayBuffer);
}
function base64ToBinary (base64EncodedFile) {
var BASE64_MARKER = ';base64,';
var base64Index = base64EncodedFile.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
var base64 = base64EncodedFile.substring(base64Index);
var raw = atob(base64);
var rawLength = raw.length;
var array = new Uint8Array(rawLength);
for (i = 0; i < rawLength; i++)
{
array[i] = raw.charCodeAt(i);
}
return array.buffer;
}
When I wrote a similar piece of code for a project, I noticed that SharePoint (or just IE) had trouble getting the MIME types correct. I ended up stripping it from the image to make it work, as below.
var raw = atob(base64.replace(/^data:image\/(png|jpg);base64,/, ""));
Uploading to SharePoint image library using the REST API and Ajax
If you decide to not go for an Angular module to upload your file, you can instead upload files directly to a SharePoint library through the REST API using normal ajax calls with jQUery. This might have to be modified for the Angular syntax, but the concept is the same.
var requestUrl = String.format("{0}/_api/web/lists/getByTitle('Images')/rootfolder/files/Add(url='{1}', overwrite=true)", _spPageContextInfo.siteAbsoluteUrl, fileName);
$.ajax({
url: requestUrl,
type: "POST",
data: buffer, //This is the base64 encoded buffer from the above step
processData: false,
headers: {
Accept: "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val()
},
success: function(result) {
console.log("Upload complete!");
},
error: function(error) {
console.log("Something went wrong!");
}
});

Related

model does not change angularjs

I have client list in a table.
When I click on editClient, the name of the client will be displayed in an input text. This work perfectly.
<body ng-app="myClientApp" ng-controller="myClientController">
<a class="btn btn-success" ng-click="chargerClients()">
Charger Clients
</a>
<div ng-if="clients">
<table>
<tr ng-repeat="cl in clients >
<td>{{cl.idClient}} </td>
<td>{{cl.nomClient}} </td>
<td> <a class="btn btn-success" ng-click="editClient(cl.idClient,cl.nomClient)"></td>
</table>
<div>
<input type="text" ng-model="id">
<input type="text" ng-model="nom">
<button ng-click="modifyClient()"> validate</button>
</div>
</div>
</body>
The problem is when I click on modifyClient, it keeps the same values and nothing happens. How can I fix this problem?
<script>
var app=angular.module("myClientApp", []);
app.controller("myClientController", function($scope,$http,$window) {
$scope.chargerClients=function(){
$http.get("/clients")
.success(function(data){
$scope.clients=data;
});
};
//load id and name
$scope.editClient=function(idClient, nomClient){
$scope.id=idClient;
$scope.nom=nomClient;}
//modifyClient
$scope.modifyClient=function(){
var params="";
var params = ({
idClient:$scope.id,
nomClient: $scope.nom});
$http({
method: 'PUT',
url: "clients",
data: params,
headers: {'Content-type': 'application/json'}
})
.success(function(data) {
$window.alert($scope.id+$scope.nom);
$scope.chargerClients();
$window.location.href = '/index.html'
})
};
}
</script>
Try using POST method in your modifyClient
Thank you i solve it; i have to add link in ng-model:
`<ng-model="client.id">`
and in the script also:
$scope.client={}
$scope.editClient=function(idClient, nomClient){
$scope.client.id=idClient;
}
$scope.modifyClient=function(){
var params="";
var params = ({
idClient:$scope.client.id
});

Pass text box value to services in angular

I have two pages-one is to create data and when I click save button text box values will be send to backend method.In another page am displaying those entered datas in table.So am using two controller methods here.
I dont know how to send text box values to backend using angular.I did it using jquery simply but I dont know angular thats why am struggling.
This is my first page to save text box details:
<div class="row ">
<label>Name<span id="required">*</span></label>
<input type="text" ng-model="item.name" class = "col-lg-5 col-md-5 col-sm-5 col-xs-10"/>
</div>
<div class="row ">
<label class="col-lg-2 col-md-2 col-sm-3 col-xs-12 ">Description</label>
<textarea ng-model="item.description"></textarea>
</div>
<div class="row marTop">
<span class="pull-right">
<button class="btn save btn-primary" ng-click="addItem(item)"><i class="fa fa-floppy-o"></i>Save</button>
<button class="btn cancel btn-default" onclick="window.location.href = '/Admin/RoleList'"><i class="fa fa-ban"></i>Cancel</button>
</span>
</div>
Script: In this method only I need to pass name and description values
<script>
var app=angular
.module("intranet_App", [])
.controller('myCtrl', function ($scope, $http) {
$scope.items = [];
$scope.addItem = function (item) {
$scope.items.push(item);
$scope.item = {};
}
//$scope.item = aaa;
console.log(item)
//$scope.values = {
// name: 'newroleName',
// description: 'roledescription'
//};
$http.post("/Admin/RolesInsert"){
alert("success")
}
})
</script>
This is my second page to get table data( that saved name should be display in this table)
<table class="table table-hover table-bordered" id="mydata" ng-controller="myCtrl">
<thead class="colorBlue">
<tr>
<th>S.No</th>
<th>Name</th>
<th>Action</th>
</tr>
</thead>
<tbody id="">
<tr ng-repeat="x in roleList | filter:searchText">
<td>{{x.Id}}</td>
<td>{{x.name}}</td>
<td>
<i class="edit fa fa-pencil-square-o" id="edit{{x.Id}}" ng-click="edit{{x.Id}}"></i>
<i class="update fa fa-floppy-o" id="update{{x.Id}}" ng-click="update{{x.Id}}"></i>
<i class="editCancel fa fa-times" id="editCancel{{x.Id}}" ng-click="cancel{{x.Id}}"></i>
</td>
</tr>
</tbody>
</table>
script for second table
<script>
var app=angular
.module("intranet_App", [])
.controller('myCtrl', function ($scope, $http) {
$scope.values = {
};
$http.post("/Admin/getRolesList")
.then(function (response) {
$scope.roleList = response.data;
});
})
</script>
One of the ways of doing this is:
angular.module("intranet_App", [])
.controller('myCtrl', function ($scope, $http, myFactory) {
...
function sendDataToBackend() {
var requestHeaders = {
"Content-Type": 'application/json'
}
var httpRequest = {
method: 'POST',
url: 'your url',
headers: requestHeaders
};
httpRequest.data = $scope.items;
$http(httpRequest).then(function (response) {
//Handle the response from the server
})
}
}
Finally got an answer:
<script>
var app=angular
.module("intranet_App", [])
.controller('myCtrl', ["$scope","$http", function ($scope, $http ,myFactory) {
$scope.items = [];
$scope.addItem = function (item) {
$scope.items.push(item);
//$scope.oRoles = $scope.item
$scope.json = angular.toJson($scope.item);
console.log($scope.json)
}
$scope.myFunc = function (item) {debugger
$scope.addItem(item);
var requestHeaders = {
"Content-Type": 'application/json'
}
var httpRequest = {
method: 'POST',
url: '/Admin/RolesInsert',
headers: requestHeaders
};
httpRequest.data = $scope.json;
$http(httpRequest).then(function (response) {
alert(response)
//$window.location.href = '/Admin/RoleList';
})
}
}])
</script>

Can't access the specified url using rest and angularjs

I am trying to get data using REST api from html form using angularjs and do some db operation on it. I am getting 404 error for the rest link specifid.
Here's my js code
var app=angular.module("myApp",[]);
app.controller("mycon",function($scope,$http){
console.log("entered here");
$scope.test={};
$scope.add = function() {
console.log("entered here");
var json=JSON.stringify($scope.test);
console.log($scope.test);
console.log(json);
$http({
url: "rest/xyz/role",
method: "GET",
data: json,
headers: {'Content-Type': 'application/json'}
})
.success(function(data, status,header,config) {
$scope.data = data;
}).error(function(data, status,header,config) {
alert("error");
});
}});
<body ng-app="myApp" ng-controller="mycon">
<center>
<h2> Login Here! </h2>
<hr/>
<form >
<table>
<tr>
<td>Signum Id:</td>
<td><input type="text" ng-model="test.sig"/></td>
</tr>
<tr>
<button class="btn waves-effect waves-light" type="submit" ng-click="add()" name="action"> Submit <i class="material-icons right">send</i>
</tr>
</table>
</form>
</center>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/js/materialize.min.js"></script>
</body>
and my REST code goes here.
#Path("/xyz")
public class RestServices {
#GET
#Path("/role")
#Produces({ "application/json" })
public String list() {
//do db operation
}
}
After deploying and running the project on server, I am getting following error:
http://localhost:8080/LoginEmployee/rest/xyz/role "404 NOT FOUND".
Add servlet mapping in web.xml as "rest/*". and also check the project name which should be "LoginEmployee"
Try removing rest/ from $http param.
url: "xyz/role",

AngularJS Not Getting Latest Data From Database

I have a factory.all() function that gets called on page load. However, whenever I enter a new entry into my MongoDB or delete one, it is not refreshing. I am logging (data) to console to see how many objects are returned. Currently, I have four being returned. Even when I delete one of them, and refresh the page, 4 objects are still logged to the console. Is this a Browser caching issue? Is there a way to counter this?
My controller:
angular.module('quizCtrl', [])
.controller('quizController', function(Quiz) {
// Assign local variable to be used in application
var vm = this;
// To Load All Quizzes on Application
Quiz.all().success(function(data) {
console.log(data);
});
My Factory:
angular.module('quizService', [])
.factory('Quiz', function($http) {
// create a new object
var quizFactory = {};
// get a single quiz
quizFactory.get = function(id) {
return $http.get('/api/quiz/' + id);
};
// get all quizzes
quizFactory.all = function() {
return $http.get('/api/quiz/');
};
// create a quiz
quizFactory.create = function(quizData) {
return $http.post('/api/quiz/', quizData);
};
// update a quiz
quizFactory.update = function(id, quizData) {
return $http.put('/api/quiz/' + id, quizData);
};
// delete a quiz
quizFactory.delete = function(id) {
return $http.delete('/api/quiz/' + id);
};
// return our entire quizFactory object
return quizFactory;
});
Endpoint:
// GET request to load ALL quiz at once
apiRouter.route('/quiz')
.get(function(req, res) {
Quiz.find({}, function(err, quiz) {
if (err) res.json({ message: "Error: " + err})
res.json(quiz);
});
});
// GET request to get a specific quiz only
apiRouter.route('/quiz/:quiz_id')
// get the user with that id
.get(function(req, res) {
Quiz.findById(req.params.quiz_id, function(err, quiz) {
if (err) res.json("Error: " + err);
// return that user
res.json(quiz);
});
});
HTML Displaying Data
<div class="panel panel-success" ng-show="quiz.quiz">
<div class="panel-heading">
<div class="panel-title">{{ quiz.quiz.question }}
<div style="float:right">
{{ ex.createdAt | date : "MMM d, y h:mm a" }}
</div>
</div>
</div>
<div class="panel-body">
<button type="button" class="btn btn-default" ng-click="quiz.submitAnswer(quiz.quiz.answers[0], quiz.quiz._id, quiz.quiz.correctAnswer)" ng-disabled="quiz.isDisabled">A. {{ quiz.quiz.answers[0] }}</button><br><br>
<button type="button" class="btn btn-default" ng-click="quiz.submitAnswer(quiz.quiz.answers[1], quiz.quiz._id, quiz.quiz.correctAnswer)"" ng-disabled="quiz.isDisabled">B. {{ quiz.quiz.answers[1] }}</button><br><br>
<button type="button" class="btn btn-default" ng-click="quiz.submitAnswer(quiz.quiz.answers[2], quiz.quiz._id, quiz.quiz.correctAnswer)" ng-disabled="quiz.isDisabled">C. {{ quiz.quiz.answers[2] }}</button><br><br>
<button type="button" class="btn btn-default" ng-click="quiz.submitAnswer(quiz.quiz.answers[3], quiz.quiz._id, quiz.quiz.correctAnswer)"" ng-disabled="quiz.isDisabled">D. {{ quiz.quiz.answers[3] }}</button><br><br>
<div class="alert alert-info" role="alert" ng-if="(quiz.successMessage)">
<strong>{{ quiz.successMessage }}</strong> is correct.
</div>
<div class="alert alert-danger" role="alert" ng-if="(quiz.failureMessage)">
<strong>{{ quiz.failureMessage }}</strong> is incorrect.
</div>
<div class="alert alert-success" role="alert" ng-if="(quiz.correctMessage)">
Correct answer is: <strong>{{ quiz.correctMessage }}</strong>
</div>
Correct So Far: {{ quiz.correctSoFar }}
</div>
<div class="panel-body">
<div class="panel-body">Posted by: {{ exam.postedBy }}</div>
<div style="float:right">
<button class="btn btn-success" type="button" ng-click="quiz.nextQuestion()" ng-if="quiz.isDisabled">Next</button>
</div>
</div>
</div>
</div>

How to send value of dropdown in backend in angularjs?

I am using Spring + AngularJS. How to send value of dropdown in backend in angularjs?
HTML:
<div class="col-md-4">
<select ng-model="algoList">
<option ng-repeat="algo in algoList" value="{{algo}}">{{algo}}</option>
</select>
<button class="btn btn-primary" ng-click="applyAlgo()">
<span class="glyphicon glyphicon-right"></span> Apply
</button>
</div>
JS:
$scope.algoName = "";
$scope.algoList= ["DC_CleaningOperations","FilerOperation"];
$scope.applyAlgo = function() {
var response = $http.post('/idw-dv/getAlgo', $scope.algoName);
response.success(function(data, status, headers, config) {
swal("Following algorithm is applied successfully. :",data,"success");
console.log(data);
});
response.error(function(data, status, headers, config) {
swal( "Exception details: " + JSON.stringify({data: data}));
});
Controller:
#RequestMapping(value = "/getAlgo", method = RequestMethod.POST)
#ResponseBody
public String getAlgorithm(#RequestBody String algoName) {
return algoName;
}
So here was the problem, the model you defined for select field is wrong and will eventually lead you to problem.
The selected value from dropdown will now be stored in algoName if you change the ng-model to "algoName".
This value will now be transferred to Spring Controller as a String.
Hope this works...
<div class="col-md-4">
<select ng-model="algoName">
<option ng-repeat="algo in algoList" value="{{algo}}">{{algo}}</option>
</select>
<button class="btn btn-primary" ng-click="applyAlgo()">
<span class="glyphicon glyphicon-right"></span> Apply
</button>
</div>

Resources