How do I upload a file to an ng-repeated model? [duplicate] - angularjs

This question already has answers here:
File Upload using AngularJS
(29 answers)
Closed 5 years ago.
I have an angular controller that is supposed to update person data. With text and date fields, that works just fine, I have
<ul>
<li ng-repeat="person in $ctrl.persons | filter:$ctrl.query">
...
<div ng-show="person.edit">
<label>Full Name*:</label><input class="edit-person" ng-model="person.fullname" /><br />
<label>Birthdate:</label><input class="edit-person" type="date" ng-model="person.birthdate" /><br />
<label>Deathdate:</label><input class="edit-person" type="date" ng-model="person.deathdate" /><br />
<label>Description: </label><input class="edit-person" type="text" ng-model="person.description" /><br />
<img ng-src="{{person.picture}}" width="100px" height="100px" /><br />
<label>Picture: </label>
<input class="edit-person" type="file" accept="image/*"
ng-file-select="handleEditPersonFiles(this.files);" /><br />
<button ng-click="$ctrl.submitEdit(person); person.edit = false;">submit</button>
<button ng-click="$ctrl.cancelEdit(); person.edit = false;">cancel</button>
</div>
</li>
</ul>
and the component code:
var self = this;
this.submitEdit = function(person){
$http.post('/edit_person', {
id: person.id,
fullname: person.fullname,
birthdate: person.birthdate,
deathdate: person.deathdate,
description: person.description,
picture: person.picture
}).then(loadPersons);
};
and
handleEditPersonFiles = function(files){
var reader = new FileReader();
var that = this;
reader.onload = function(){
? = reader.result;
};
reader.readAsDataURL(files[0]);
};
I have no problem reading and uploading the pictures in the new-person function, since there I have a single variable, and can just self.new_person_picture = reader.result, but with the edit function, I don't know where to assign the reader result since I don't have access to the person.picture variable through angular. The onchange event correctly submits the file list. But ng-change seems to require a model, and doesn't fire when a file is selected. I also tried ng-file-select, but no event seems to be firing when I select a file to upload. Any help would be greatly appreciated.

It's easier than you think, you just have to pass the person model to the handleEditPersonFiles model too.
html:
<li ng-repeat="person in $ctrl.persons ...
...
<label>Picture: </label><input class="edit-person" type="file" accept="image/*" ng-file-select="handleEditPersonFiles(person, this.files);" />
js:
handleEditPersonFiles = function(person, files){
var reader = new FileReader();
reader.onload = function(){
person.picture = reader.result;
};
reader.readAsDataURL(files[0]);
};

Related

how to remove the value of an input field using angularjs

<div class="info-block" ng-app="">
<div ng-controller="Note">
<div class="checkbox">
<label>
<p><b>Primary Publication: </b>
{{ form_widget(form.input_ppubs, { 'attr': {'class': 'valOption'}}) }}
</p>
</label>
</div>
<div ng-repeat="item in items">
<input type="text" placeholder="new input" ng-model="item.primaryPub">
</div>
<button type="button" ng-click="add()">New Item</button>
</div>
I am trying to retrieve the value of the html input field and remove it from input upon a button click
I am able to get the code, but I don't know how to remove the code.
var Note = function($scope){
$scope.items = [];
$scope.add = function () {
//angular way of implementing document.getElementByID();
pub1 = angular.element('#form_input_ppubs').val();
$scope.items.push({
primaryPub: pub1
});
};
}
You don't have to retrieve your items like this. It's ugly and not the angular way. angular.element('#form_input_ppubs').val();
Instead, simply reference it in your input using ngModel.
Declare it in your scope.
$scope.inputItem = null;
HTML
<input ng-model="inputItem " />
Use it in your function:
$scope.addItem = function(item) {
$scope.items.push(item);
//reset the model
$scope.inputItem = null;
}
Call it using ng-click
<button type="button" ng-click="addItem(inputItem)">Add Item</button>
If you do:
console.log($scope.items);
You should see an entry for primaryPub, the model for your input. Then you can target it by nulling the model, so:
$scope.items.primaryPub = null;
However you're using this inside an ng-repeat:
<div ng-repeat="(i, item) in items">
<input type="text" placeholder="new input" ng-model="items[i].primaryPub">
</div>
So your console.log (if you have more than one item in 'items') should show an array-like structure for primaryPub.

ng-model not change after save editing

i try to make simple CRUD with angularjs and php api
the problem is in angularjs
i have code like this :
$scope.editData = function(pid) {
$scope.hideform = false;
$scope.edit = false;
$scope.pid = $scope.projects[pid].pid;
$scope.title = $scope.projects[pid].title;
$scope.pcode = $scope.projects[pid].pcode;
$scope.type = $scope.projects[pid].type;
$scope.proj_type = $scope.projects[pid].proj_type;
};
$scope.saveData = function(pid, title, pcode, type2, proj_type){
$http.post("api/getProject.php",
{type: "edit", id:pid, title:title, pcode:pcode, type2:type2, proj_type:proj_type})
.success(function(data) {
notification(data.success, data.message);
$scope.hideform = true;
});
};
and have form for editing data (edit button clicked , then show form edit with ng-model loaded on it
like this
<form class="form-horizontal" ng-hide="hideform" ng-submit="saveData(pid,title, pcode, type, proj_type)">
<h3 ng-hide="edit">Edit Project:</h3>
<div class="form-group">
<label class="col-sm-2 control-label">PID:</label>
<div class="col-sm-10">
<input type="text" ng-model="pid" ng-disabled="!edit" placeholder="PID">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Title:</label>
<div class="col-sm-10">
<input type="text" ng-model="title" placeholder="Title">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Pcode:</label>
<div class="col-sm-10">
<input type="text" ng-model="pcode" placeholder="Pcode">
</div>
</div>
<button class="btn btn-success" ng-disabled="error || incomplete">
<span class="glyphicon glyphicon-save"></span> Save Changes
</button>
</form>
the script are working , but everytime i click save editing then click edit button (on each row on table) , the ng-model on form input still same like the last data what i save but other input are changed , ex : i edited title , when click edit button on different row on the table , just pcode changed to different row data , the Title still same like the last data i edit
sorry if my explanation make all of you confuse
Any help will be appreciated
here is the image if my explanation not clear
This problem resolved using
$scope.selectedProject = $scope.projects[pid];
so editData function look like this
$scope.editData = function(pid) {
$scope.hideform = false;
$scope.edit = false;
$scope.pid = $scope.projects[pid].pid;
$scope.title = $scope.projects[pid].title;
$scope.pcode = $scope.projects[pid].pcode;
$scope.type = $scope.projects[pid].type;
$scope.proj_type = $scope.projects[pid].proj_type;
$scope.selectedProject = $scope.projects[pid];
};
and ng-model (on every input)
need to change like this
<input type="text" ng-model="selectedProject.pid" ng-disabled="!edit" placeholder="PID">
instead of this
<input type="text" ng-model="pid" ng-disabled="!edit" placeholder="PID">
Now every ng-model changed every edit button has been click after save Changes button clicked :)
Thank you!

Adding hidden form field to array in Angular

I am trying to add a "hidden" field to a basic form in Angular (using Firebase as the backend). I'm having trouble figuring out how to include this field as part of the array when the form is submitted. I want to include {type: 'Basic'} as part of the array. I've looked at the other related posts on this site, but am still unsure how to apply to my particular situation.
Any suggestions on how to do this?
Javascript:
myApp.controller('NewProjectCtrl', function ($location, Projects) {
var editProject = this;
editProject.type = 'Basic'; //this is the hidden field
editProject.save = function () {
Projects.$add(editProject.project).then(function(data) {
$location.path('/');
});
};
});
HTML:
<form>
<div class="control-group form-group">
<label>Name</label>
<input type="text" name="name" ng-model="editProject.project.name">
</div>
<label>Description</label>
<textarea name="description" class="form-control" ng-model="editProject.project.description"></textarea>
<button ng-click="editProject.save()" class="btn btn-primary">Save</button>
</form>
You don't need a hidden form field, just submit your value in your controller like this:
editProject.save = function () {
editProject.project.type = 'Basic';
Projects.$add(editProject.project).then(function(data) {
$location.path('/');
});
};
All attributes of your editProject.project will be submitted, as you may notice in the developer console.
I would structure the controller a bit different.. here is an example (I am considering you are using angular-resource, where Projects returns a Resource?):
myApp.controller('NewProjectCtrl', function ($location, Projects) {
$scope.project = new Projects({type: 'Basic'});
$scope.save = function () {
$scope.project.$save().then(function(data) {
$location.path('/');
});
};
});
<form ng-submit="save()">
<div class="control-group form-group">
<label>Name</label>
<input type="text" name="name" ng-model="project.name">
</div>
<label>Description</label>
<textarea name="description" class="form-control" ng-model="project.description"></textarea>
<input type="submit" value="Save" class="btn btn-primary" />
</form>
The save function will $save the new project resource (this is an default method and will make a POST on the given resource URL).

AngularJS moving items between two select list

I am trying to move items between two select lists using the code below, but items are not moved from the availableClients list to selectedClients lists, so can someone please check the code below and let me know what I am missing here? Thanks
<div ng-app>
<div ng-controller="testCtrl">
<label for="aclients">Available Clients</label>
<select size="5" multiple ng-model="available" ng-options="client.id as client.Name for client in clientsList" style="width: 400px"></select>
<input id="moveright" type="button" value="Add Client" ng-click="moveItem(available[0], availableclients,selectedclients)" />
<input id="moverightall" type="button" value="Add All Clients" ng-click="moveAll(availableclients,selectedclients)" />
<input id="move left" type="button" value="Remove Client" ng-click="moveItem(selected[0], selectedclients,availableclients)" />
<input id="moveleftall" type="button" value="Remove All Clients" ng-click="moveAll(availableclients,selectedclients)" />
<label for="sclients">Selected Clients</label>
<select size="5" multiple ng-model="selected" ng-options="client.id as client.Name for client in selectedclients" style="width: 400px"></select>
<div>Selected Clients IDs: {{selectedclients}}</div>
</div>
</div>
Controller:
app.controller('testCtrl',
function testCtrl($scope, clientsService){
$scope.clientsList = clientsService.getClientsList().then(
function(response){
$scope.clientsList = response;
},
function(status){
console.log(status);
}
);
$scope.moveItem = function(item, from, to) {
console.log('Move item Item: '+item+' From:: '+from+' To:: '+to);
//Here from is returned as blank and to as undefined
var idx=from.indexOf(item);
if (idx != -1) {
from.splice(idx, 1);
to.push(item);
}
};
$scope.moveAll = function(from, to) {
console.log('Move all From:: '+from+' To:: '+to);
//Here from is returned as blank and to as undefined
angular.forEach(from, function(item) {
to.push(item);
});
from.length = 0;
};
$scope.availableclients = [];
$scope.selectedclients = [];
});
There are several small problems in your template:
You're moving objects from availableclients to selectedclients, but the first select displays options from clientsList, and not from availableclients
You're moving IDs rather than objects. Your ng-options should simply be
client as client.name for client in availableclients
Your remove all button moves from available to selected, instead of moving from selected to available.
Here is a working plunkr: http://plnkr.co/edit/RYEmpkBjQStoCfgpWPEK?p=preview
<label for="aclients">Available Clients</label>
<select size="5" multiple ng-model="available" ng-options="client as client.name for client in availableclients" style="width: 400px"></select>
<input id="moveright" type="button" value="Add Client" ng-click="moveItem(available[0], availableclients,selectedclients)" />
<input id="moverightall" type="button" value="Add All Clients" ng-click="moveAll(availableclients,selectedclients)" />
<input id="move left" type="button" value="Remove Client" ng-click="moveItem(selected[0], selectedclients,availableclients)" />
<input id="moveleftall" type="button" value="Remove All Clients" ng-click="moveAll(selectedclients,availableclients)" />
<label for="sclients">Selected Clients</label>
<select size="5" multiple ng-model="selected" ng-options="client as client.name for client in selectedclients" style="width: 400px"></select>
In regard to my comment/question. I actually found an answer.
So for those that come here and have the same issue, here is what I found.
When moving a item from one SELECT list to another SELECT list, the angular model on the source list can get "lost".
To avoid this, the changed to each list must be done in separate $apply function call. Here is a cut down example from within in the event handler
onClickRight = function (item, from, to) {
var self = this;
var selecteditem = angular.copy(item);
self.$timeout(function () {
self.scope.$apply(function () {
for (var idx = 0; idx < from.length; idx++) {
if (from[idx].value == item.value && from[idx].displayValue == item.displayValue) {
item.length = 0;
from.splice(idx, 1);
break;
}
};
});
}, 200);
self.$timeout(function () {
self.scope.$apply(function () {
to.push(selecteditem);
});
}, 300);
};
The 'item' is cloned with angular.copy so it can be used in the second angular $apply
My options have a 2 properties: value and displayValue
I also assign $timeout and $scope to the 'self' variable in the directive's constructor.
Hope this helps

Deleting a record from a database in HTML5

Using HTML5 code, I'm unable to delete from the database even though the onsuccess event is triggered.My delete code is as below:
btnDelete.addEventListener("click", function(){
//alert("At Delete function");
var AadharNumber = document.getElementById("AadharNumber").value;
var transaction = db.transaction("CustDetails",IDBTransaction.READ_WRITE);
var objectStore = transaction.objectStore("CustDetails");
var request = objectStore.delete(AadharNumber);
request.onsuccess = function(event){
alert( "Aadhar Number: "+ AadharNumber + " deleted from the database");
};
},false);
Then when i click the print button after the delete, i still get to see the same records.Below is my print function.
btnPrint.addEventListener("click", function () {
var output = document.getElementById("printOutput");
output.textContent = "";
var transaction = db.transaction("CustDetails", IDBTransaction.READ_WRITE);
var objectStore = transaction.objectStore("CustDetails");
var request = objectStore.openCursor();
request.onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
output.textContent += "<li>""Aadhar Number: " + cursor.key + " is " + cursor.value.name + "</li>";
cursor.continue();
}
else {
console.log("No more entries!");
}
};
}, false);
My html code is as below:
<body><center>
<div id="container">
<label for="txtName">
Name:
</label>
<input type="text" id="txtName" name="txtName" />
<br />
<label for="txtEmail">
Email:
</label>
<input type="text" id="txtEmail" name="txtEmail" />
<br />
<input type="button" id="btnAdd" value="Add Record" />
<br />
<label for="AadharNumber">
ID:
</label>
<input type="text" id="AadharNumber" name="txtAadharNumber" />
<input type="button" id="btnDelete" value="Delete Record" />
<br />
<input type="button" id="btnPrint" value="Print Records" />
<br />
<output id="printOutput" > </output>
</div>
</center>
</body>
What is wrong with my delete? Thanks.
The code seems fine however you could check if converting the string key to integer value helps deleting the object from the object store.
var AadharNumber = parseInt(document.getElementById("AadharNumber").value);

Resources