User is filling a form with different types of inputs.
On the same page he also can delete files from a server. After clicking a button a file is deleted, page is reloaded and changes made in other inputs are reset.
I've read a sessionStorage is something for me but currently I even have trouble injecting it. (Error: $injector:unpr Unknown Provider)
I think it delFile function in js controller it should be saving data to session storage, but how and where to retrieve it later?
jsp form:
<form ng-submit="save()">
<div>
Name:
<input type="text" ng-model="myForm.name" />
</div>
<div>
Type:
<select ng-model="myForm.type">
<option ng-selected="{{type.id == myForm.type}}" ng-repeat="type in types" value="{{type.id}}">{{type.description}}</option>
</select>
</div>
<div>
Is new:
<input type="checkbox" ng-model="myForm.isNew">
</div>
<div>
Files to upload:
<input type="file" file-input="filesToUpload" name="file" multiple />
<br>
Server files:
<p ng-repeat="serverFile in serverFiles" >
{{serverFile.name}}
<button type="button" ng-click="delFile(serverFile)">Delete from server</button>
</p>
</div>
<div>
<input type="submit" value="Save it!" />
</div>
</div>
</form>
js controller:
productApp.controller('ProductController', [
'$scope',
'$http',
'$log',
'$modal',
'$filter',
'$routeParams',
'$location',
'$window',
'$sessionStorage',
'productService',
function($scope, $http, $log, $modal, $filter, $routeParams, $location, $window, $sessionStorage, productService) {
$scope.productId= $routeParams.productId;
$scope.types= [];
$scope.myForm = {};
$scope.filesToUpload = [];
productService.getTypes().then(function(response) {
$scope.types = response.data;
});
productService.getServerFiles($scope.productId).then(function(response) {
$scope.serverFiles = response.data;
});
$scope.delFile = function(file) {
productService.deleteFileFromServer(file, $scope.productId);
// here it should be saving data to session storage I believe, but how and where to retrieve it later?
$window.location.reload();
};
$scope.save= function() {
$http({
method: 'POST',
url: '/product/app/save',
headers: {'Content-Type': undefined},
transformRequest: function (data) {
var formData = new FormData();
formData.append('myForm', new Blob([angular.toJson(data.myForm)], {
type: "application/json"
}));
for (var i = 0; i < $scope.filesToUpload.length; i++) {
$log.info("filesToUpload[i]: " + JSON.stringify($scope.filesToUpload[i]));
formData.append('files', $scope.filesToUpload[i]);
}
return formData;
},
data: {
myForm: $scope.myForm,
files: $scope.filesToUpload,
},
}).success(function(data) {
alert("All went well!");
$location.path('/inProgress');
}).error(function(data) {
$scope.$error = 'Error occurred!';
});
};
}
]);
SessionStorage is not an angular dependecy therefor you can not inject it.
If You really want you can create a service that wraps it and then inject service if you want to but it isn't necessary.
SessionStorage is a located on the window object which is global. Which means that you can reach it as such
sessionStorage.setItem("keyname", "YourValueAsString")
https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage
Related
I am trying to make a very minimalistic form in AngularJS (version 1).
I am trying to use ng-model and the $scope to update an object I've named fluff. Once a user clicks submit it should be used in this $http call.
I'm highly confused I thought ng-model would bind this to the object in the scope. But it always returns a blank cause the $scope.fluff is not updating.
Yet if I inject {{ fluff.link }} this will update based on the textbox.
Here is my form in the view:
<form name="fluffForm" ng-submit="submitform()">
<span>Link: <input type="text" name="link" ng-model="form.link"></span>
<span>Description: <input type="text" name="description" ng-model="form.desc"></span>
<button type="submit">submit</button>
</form>
</div>
Here is my controller:
(function(){
'use strict';
angular.module('fluff').controller('FormController', FormController);
FormController.$inject = ['$scope', '$rootScope', '$routeParams', '$window', '$http'];
function FormController( $scope, $rootScope, $routeParams, $window, $http){
var form = this;
$scope.fluff = {}; // form data in json object(?) to be posted to mongo database
$scope.submitform = function(){
$scope.fluff.link = form.link;
$scope.fluff.description = form.desc;
console.log('form-data', $scope.fluff);
$http({
method: 'POST',
url: 'http://fluff.link/share',
data: $scope.fluff,
headers: {'Content-type': 'application/x-www-form-urlenconded'}
}).success(function(data){
console.log('Call to API was successful');
if(data.errors){
console.log('Data Errors');
console.log('error:', $data.errors.name);
//show errors - part of the response in the REST API have to make this portion up myself
$scope.errorName = $data.errors.name;
} else {
console.log('returned share id', data);
var fluff = 'fluff/link/'+ data;
$window.location.href = fluff;
}
});
}
}
})();
Here is my route:
(function(){
'use strict';
angular.module('fluff').config(Config);
Config.$inject = ['$routeProvider'];
function Config($routeProvider){
$routeProvider.when('/', {
templateUrl: 'views/index.client.view.html',
controller: 'FormController',
controllerAs: 'form'
});
}
})();
Added some logs from the developer console in chrome:
in submitform FormController {link: "test", desc: "test"}
fluff.form.controller.js:24 form-data Object {link: undefined}
Got it to work! Will update with my answer when it allows!
So my problem here is that I wasn't using the form controller like I should have.
Here I have the template being loaded with the controller as form.
$routeProvider.when('/', {
templateUrl: 'views/index.client.view.html',
controller: 'FormController',
controllerAs: 'form'
});
In the template I have to use form:
<span>Link: <input type="text" name="link" ng-model="form.link"></span>
<span>Description: <input type="text" name="description" ng-model="form.desc"></span>
then in the controller I create a this object:
var vm = this;
vm is now linked to form.
So now I can do this:
var fluff = {};
fluff.link = form.link;
fluff.description = form.desc;
Now fluff has all the data it needs when my user clicks submit.
I have a localstorage value which i would want to put in it a texfield from a controller
.controller('working_ctrl', ['$scope', '$http', '$location', function ($scope, $http,$location) {
$scope.user= localStorage.getItem("user")
$scope.items = [];
$scope.selected = undefined;
$http({
method: 'GET',
url:'http://localhost/work/templates/spree/work/items.php'
}).then(function (data) {
$scope.items = data.data;
//console.log(JSON.stringify(data));
})
}])
HTML
<div ng-controller="working_ctrl" ng-repeat="s in items| limitTo:1">
<input name="quantity" type="text" id="quantity" ng-model="s.quantity">
<input name="user" type="text" id="user" ng-model="s.user">
</div>
You can bind the $scope.user to that textbox
<input name="user" type="text" id="user" ng-model="user">
your try to put the user in User input field but your input field is present with in ng-repeat so push user data in Array or set the user data in specific array index . like this
.controller('working_ctrl', ['$scope', '$http', '$location', function($scope, $http, $location) {
$scope.user = localStorage.getItem("user")
$scope.items = [];
$scope.selected = undefined;
$http({
method: 'GET',
url: 'http://localhost/work/templates/spree/work/items.php'
}).then(function(data) {
$scope.items = data.data;
//console.log(JSON.stringify(data));
$scope.item.forEach(function(value) {
value.user = $scope.user
})
or //
$scope.item[0].user = $scope.user // user specific index
})
}])
I am new to angularjs. I want to pass data from html form to another route.
Here is the part of index.html
<div ng-app="myApp" ng-controller="HomeController">
<div class="container">
<div class="row">
<div class="col-md-12">
<div ng-view=""></div>
</div>
</div>
</div>
</div>
Here are the routes
var myApp = angular.module('myApp', ['ngRoute']);
myApp.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/', {
templateUrl: 'views/home.html',
controller: 'HomeController'
});
$routeProvider.when('/about', {
templateUrl: 'views/about.html',
controller: 'AboutController'
});
}]);
When the route is / it hits the views/home.html in which it has a form
<form action="#/about" ng-submit="submitData()">
<input type="text" name="address" ng-model="user.address" />
<input type="submit" />
</form>
I have a user service whose implementation is
myApp.factory("user", function () {
return {};
});
I inject user service in HomeController like
myApp.controller("HomeController", function ($scope, user) {
$scope.user = user;
// and then set values on the object
// $scope.user.address = "1, Mars"; // when uncomment this line it can be accessed on AboutController? Why? Otherwise I cannot access user.address
console.log($scope.user);
});
Don note my comment in above code..
and passes user to AboutController like
myApp.controller("AboutController", function ($scope, user) {
$scope.user = user;
// and then set values on the object
$scope.user.firstname = "John";
$scope.user.secondname = "Smith";
console.log($scope.user);
});
Here is the about.html
<p>
{{ user.address }}
</p>
Problem: {{user.address}} doesn't work on AboutController. I can't see any output... But when i remove the comment from above code.. It only displays hardcoded values in the controller What am I missing?
This is the working demo http://ashoo.com.au/angular/#/
At the moment, all your service does is pass a blank object return {}, to any controller into which it is injected. You need a getter/setter approach, so that in your Home view you can set the data, and in your About view you can retrieve it.
So your service could look something like this:
myApp.factory("user", function () {
var dataObj = {};
return {
setData: function(data) {
dataObj.username = data.username;
},
getData: function() {
return dataObj;
}
};
});
Now you can set the data in your Home controller:
myApp.controller("HomeController", function ($scope, user) {
$scope.submitData = function(data) { //pass in ng-model
user.setData(data); //call 'user' service to set data
}
});
And call it from your About controller:
myApp.controller("AboutController", function ($scope, user) {
$scope.user = user.getData(); //Assign
console.log($scope.user.username);
});
And you html would look like:
<form action="#/about" ng-submit="submitData(user.username)">
<input type="text" name="address" ng-model="user.username" />
<input type="submit" />
</form>
Right now I have a post method that works fine in a controller but what's the best way to refactor this into a service? Most importantly, I need to be able to pass $scope.tag from ng-model in the post. Then the post makes a call to the server for an external API request using the post params in the url.
// controller
app.controller('MainCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.submit = function () {
var recipe = $scope.tag;
$http.post('/api', {tag: recipe})
.then(function(response) {
$scope.recipeData = JSON.parse(response.data);
console.log(response.data);
});
};
// server.js
app.post('/api', function (req, res) {
var recipe = req.body.tag;
request("http://externalapi.com/api/search?key=xxx=" + recipe, function (error, response, body) {
res.json(body);
});
});
// index.html
<form class="form-inline" ng-submit="submit()">
<div class="form-group">
<input type="text" ng-model="tag" class="form-control">
<button type="submit" value="Search" class="btn btn-default search-button"> Search</button>
</div>
</form>
---------refactored code----------
app.factory('searchFactory', ['$http', function ($http) {
var obj = {};
obj.fetchRecipes = function () {
return $http.post("/api", { tag: "chicken" });
};
return obj;
}]);
app.controller('MainController', ['$scope', 'searchFactory', function ($scope, searchFactory) {
$scope.submit = function () {
searchFactory.fetchRecipes()
.success(function(response) {
$scope.recipeResults = response;
});
};
}]);
Refactor request method to a factory service and put request logic in there. ie. SearchService
So, inject SearchService in MainController and access the service request method that returns a promise.
Example:
app.controller('MainCtrl', ['$scope', 'SearchService',
function ($scope, SearchService) {
$scope.submit = function () {
var promise = SearchService.getRecipe( $scope.tag );
..
}
}
]);
Have a look at some of the style guides and best practices by the community, recommended JohnPapa's Styleguide.
I have a question for all you AngularJs gurus out there. I am attempting to create modal wherein a user can submit files for upload. I have most of the problem sorted, however, I seem to be running into issues concerning scope. The technologies I am using are Angularjs, Angular UI Bootstrap and a custom file model directive.
I have a custom fileModel directive which on file selection updates the scope:
app.directive('fileModel', ['$parse', function($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function() {
scope.$apply(function() {
modelSetter(scope, element[0].files[0]);
});
});
}
}
}]);
I use UI bootstrap to create the modal as per the documentation (http://angular-ui.github.io/bootstrap/#/modal). Please note the file-model="file" directive in the input field, this is what I am trying to access.
<div ng-controller="ModalDemoCtrl">
// Button to open model
<button class="btn btn-default" data-ng-click="open()">Upload File</button>
// Simple Form in model
<script type="text/ng-template" id="myModalContent.html">
<form name="form.myForm" class="form-horizontal" data-ng-submit="addFile()" role="form" novalidate>
<div class="modal-header">
<h3 class="modal-title">Upload File</h3>
</div>
<div class="modal-body">
<div class="form-group">
<label for="file" class="col-sm-2 control-label">Input File</label>
<div class="col-sm-10">
<input type="file" name="file" file-model="file">
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-default">Submit</button>
</div>
</form>
</script>
</div>
Lastly I have the controller(s), again as per the Bootstrap UI documentation. Please note where I try to access $scope.file.
app.controller('ModalDemoCtrl', ['$scope', '$http', '$modal', function ($scope, $http, $modal) {
$scope.open = function () {
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: ModalInstanceCtrl,
resolve: {
$http: function () {
return $http;
}
}
});
modalInstance.result.then(function () {
// do something
}, function () {
// do something
});
};
}]);
var ModalInstanceCtrl = function ($scope, $modalInstance, $http) {
$scope.addFile = function() {
var formData = new FormData();
formData.append('file', $scope.file);
$http.post(
'/valid/ajax/url', formData, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
}).success(function(data, status, headers, config) {
// do something on success
});
);
};
I know there are some issues with regards to scope within modals when using angular UI bootstrap... unfortunately I am not experienced enough to find a solution. Currently, I am unable to access the file a user selects to be sent via ajax. Please help. Thanks.
I saw that the variable "$scope.file" is not being set, it stays undefined. Therefore you can't post the file. An easy way to share data between controllers (you have two, the modal controller and you parent controller) is using a service or factory. Check documentation if you are not sure. Then you can change the save the file via service/factory and use it in both controllers.
First of all the service which just contains a getter and a setter:
app.service('fileService', function () {
var file;
var fileService = {};
fileService.getFile = function () {
return file;
};
fileService.setFile = function (newFile) {
file = newFile;
};
return fileService;
});
You can then use the service via dependency injection on the directive and the controller:
app.directive('myFileUpload', function (fileService) {
return function (scope, element) {
element.bind('change', function () {
fileService.setFile(element[0].files[0]);
});
}
});
app.controller('ModalInstanceCtrl', function ($scope, $modalInstance, $http, fileService) {
$scope.addFile = function () {
var file = fileService.getFile();
console.log(file);
$http.post(
'http://posttestserver.com/post.php', file, {
transformRequest: angular.identity,
headers: {'Content-Type': file.type}
}).success(function (data, status, headers, config) {
console.log(data);
});
};
});
I created a fiddle so you can test it there. The file is outputted on the console. For testing the post I used http://posttestserver.com/post.php
http://jsfiddle.net/dz5FK/