MEAN with Jade template form submit GET instead of POST - angularjs

So, earlier today I had a working form that could post and delete restaurants documents to a mongodb collection. Everything was working fine, but then I decided to try and load the form into a div instead of redirect to a new page. Doing so produced a different result when I tried to submit my restaurant form. Originally it would call $scope.add() in my restaurantsController, but now it is sending a GET request with form data to /restaurants instead of a POST to /api/restaurants. I'm looking for some insight as to what I did to change the behavior. Although it is loading the form when I click on my restaurant anchor tag, it is not loading the restaurants from the database.
Here is the jade and js for the menu anchors:
menu.js
app.controller("menu", ["$scope", "$http", function ($scope, $http) {
$scope.home = function () {
$("#content").html("");
};
$scope.restaurants = function () {
$http.get('/restaurants').
success(function(data, status, headers, config){
$("#main_content").html(data);
}).
error(function(data, status, headers, config){
});
};
}]);
nav.jade
mixin link(name, fn)
li
a.btn(ng-click=fn)= name
nav.navbar.navbar-inverse.navbar-fixed-top(role='navigation')
.container
.navbar-header
button.navbar-toggle.collapsed(type='button', data- toggle='collapse', data-target='#navbar', aria-expanded='false', aria- controls='navbar')
span.sr-only Toggle navigation
span.icon-bar
span.icon-bar
span.icon-bar
a.navbar-brand(href='/') Food App
#navbar.navbar-collapse.collapse
ul.nav.navbar-nav(ng-controller="menu")
+link("Home", "home()")
+link("Restaurants", "restaurants()")
And here is the form:
form(name="NewRestaurant" ng-submit="$event.preventDefault();add()")
.row
.form-group
input.form-control(type="text", name="name" placeholder="Name", ng-model="name" required)
.row
.form-group
input.form-control(type="text", name="address" placeholder="Address", ng-model="address" required)
.row
.form-group.col-md-6
-for(var i = 0; i <= 5; i++){
input(name="rating" type="radio", value=i, ng-model="rating" required)
=i
-}
.form-group.col-md-6
button.success(type="submit") Submit
and the controller...
app.controller("restaurants", ["$scope", "$resource", function ($scope, $resource) {
var Restaurant = $resource('/api/restaurants/:id');
var clearForm = function () {
$scope.name = '';
$scope.address = '';
$scope.rating = null;
}
clearForm();
var validRestaurant = function () {
if($scope.name !== '' && $scope.address !== '' && $scope.rating !== null)
return true;
else{
toastr.error("Please fill in all required form fields.");
return false;
}
}
$scope.query = function(){
Restaurant.query(function (results) {
$scope.restaurants = results;
});
};
$scope.add = function () {
alert("got here!");
if(validRestaurant()){
var restaurant = new Restaurant();
restaurant.name = $scope.name;
restaurant.address = $scope.address;
restaurant.rating = $scope.rating;
alert(restaurant);
Restaurant.save(restaurant, function (result) {
$scope.restaurants.push(result);
toastr.success("Saved " + $scope.name + ".")
clearForm();
});
}
};
$scope.update = function (id) {
};
$scope.remove = function (id) {
console.log(id);
Restaurant.delete({id: id}, function (err) {
console.log(err);
$scope.query();
});
};
$scope.query();
}]);
edit: Now that I am typing this up, I am wondering, maybe angular doesn't recognize the form and doesn't create a $scope for it because it gets loaded after the page loads...?

Related

How to bind data in 'value' attribute of <input tag> to NET core MVC model using angular

I’ve been playing around with Upload file - Streaming method. The original code, here:
https://github.com/aspnet/Docs/tree/master/aspnetcore/mvc/models/file-uploads/sample/FileUploadSample
However, I’m trying to get the data in the value attribute of <input value=” ”> using Angular, the idea is that I can POST the value into my MVC model instead of whatever is typed by the user (as in the original code). So, I have done this change to the input value property.
Streaming/Index.cshtml:
<div ng-app="myApp">
<div ng-controller="myCtrl">
..
<input value="#Model.name” type="text" name="Name" ng-model="name"/>
..
<button ng-click="createUser()">Create User</button>
..
</div>
</div>
#section scripts{
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="~/js/app.js"></script>
}
However, with Angular code running under app.js, the following piece of code actually fails with status code 400. This is because the passed value is “” and not the data under of value attribute of the HTML input tag.
App.js:
var User = (function () {
function User(name) {
this.name = name;
}
return User;
}());
var myApp = angular.module('myApp', []);
myApp.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]);
});
});
}
};
}]);
myApp.service('userService', ['$http', function ($http) {
this.createUser = function(user) {
var fd = new FormData();
fd.append('name', user.name);
return $http.post('/streaming/upload', fd, {
transformRequest: angular.identity,
headers: {
'Content-Type': undefined
}
});
};
}]);
myApp.controller('myCtrl', ['$scope', 'userService', function ($scope, userService) {
$scope.createUser = function () {
$scope.showUploadStatus = false;
$scope.showUploadedData = false;
var user = new User($scope.name);
userService.createUser(user).then(function (response) { // success
if (response.status == 200) {
$scope.uploadStatus = "User created sucessfully.";
$scope.uploadedData = response.data;
$scope.showUploadStatus = true;
$scope.showUploadedData = true;
$scope.errors = [];
}
},
function (response) { // failure
$scope.uploadStatus = "User creation failed with status code: " + response.status;
$scope.showUploadStatus = true;
$scope.showUploadedData = false;
$scope.errors = [];
$scope.errors = parseErrors(response);
});
};
}]);
function parseErrors(response) {
var errors = [];
for (var key in response.data) {
for (var i = 0; i < response.data[key].length; i++) {
errors.push(key + ': ' + response.data[key][i]);
}
}
return errors;
}
The solution must be a simple one, but after much research, I haven’t been able to find out how to modify it to make the data in the value=’’” attribute being passed across. This might be a stupid question but a headache for me however since I’m a total newbie regarding Angular. Please have some mercy, help.
Thanks
Use the ng-init directive to initialize the model:
<input ng-init="name= #Model.name" type="text" name="Name" ng-model="name"/>

No popup window with AngularJS and typeahead

I have a problem with the typeahead directive. I try to get datas from my datas from my service via $http.get.
In the console output I can see that my datas are coming from the service but I don't get the popup window of the results.
Here is my code:
Html Template:
<input type="text" class="form-control" placeholder="Kundensuche" ng-model="selectedCompany" typeahead="c for c in companies($viewValue)" typeahead-no-results="noResults" typeahead-min-length="3">
Service:
var _search = function (route, id) {
return $http.get(serviceBase + 'api/' + route + '/search/' + id);
};
serviceHelperFactory.search = _search;
Controller:
$scope.companies = function (val) {
var output = [];
var promise = serviceHelper.search('companies', val);
promise.then(function (result) {
result.data.forEach(function (company) {
output.push(company.companyName);
//output.push(company);
});
console.log(output);
}, function (error) {
adminInvoiceService.serviceErrorMessage(error);
});
return output;
}
Thanks!
Ok, I fixed it!
For all with the same problem here is my solution!
$scope.companies = function (val) {
return $http.get('http://localhost:5569/api/companies/search/'+val).then(function (res) {
var companies = [];
console.log(companies);
res.data.forEach(function (item) {
companies.push(item);
});
console.log(companies);
return companies;
});
};

how to implement ng-model value from another view in ionic

I want to display ng-model value from page to input in another page
I Want display selected issue from issues page to contact page
Issue Controller
.controller('IssueCtrl', function($scope, $http) {
$http.get('api/issues').then(function(resp) {
console.log('Success', resp);
$scope.issues = resp.data;
}, function(err) {
console.error('ERR', err);
$scope.issues = err;
});
})
Contact Controller
.factory('Post', function($resource) {
return $resource('api/add_new_order',{problem: "#problem"});
})
.controller('ContactCtrl', function($scope, Post) {
// Get all posts
$scope.posts = Post.query();
// Our form data for creating a new post with ng-model
$scope.postData = {};
$scope.newPost = function() {
var post = new Post($scope.postData);
post.$save();
}
$scope.issues = {};
$scope.answer = function(){
console.log($scope.issues.name);
}
})
Issue View
<ion-list ng-repeat="item in issues">
<ion-radio ng-model="issues.name" ng-value="'{{item.issue}}'">
{{item.issue}}
</ion-radio>
</ion-list>
Contact View
<form ng-submit="newPost()">
<label class="item item-input">
<span class="input-label">Problem :</span>
<input type="text" name="problem" ng-model="postData.problem">
</label>
</form>
Your API requests should be on independent services, so they can be accessed by any controller.
As you seen to know how a factory works, I will give you an example.
.factory('IssuesService', function($http) {
var issues = [];
return {
all: function() {
return $http.get('api/issues')
.then(function(data){ // Optional callback inside service
issues = data;
});
}
}
})
.controller('ContactCtrl', function($scope, Post, IssuesService) {
...
$scope.issues = [];
IssuesService.all().then(function(data){
$scope.issues = data;
})
...
})
.controller('IssueCtrl', function($scope, $http) {
IssuesService.all()
.then(function(resp) {
console.log('Success', resp);
$scope.issues = resp.data;
}, function(err) {
console.error('ERR', err);
$scope.issues = err;
});
})

How to Dismiss Angular Modal

I am using Ekathuwa modals, I need to close it after a successfull Ajax PUT. I am trying to follow the examples they give. I am able to close the modal, but there is still a grey color on the screen. Like it is still open in the background? I still need to refresh the page for it to go away.
$scope.updateJob = function (job) {
console.log($scope.currentItem);
job.JobTypeId = $scope.currentItem.JobType.JobTypeId;
job.JobClassId = $scope.currentItem.JobClass.JobClassId;
job.GeoAreaId = $scope.currentItem.GeoArea.GeoAreaId;
jobFactory.updateJob(job).success(successCallback)
.error(errorCallback);
console.log(job);
var p = $ekathuwa.modal({
id: "EditJobModal", contentStyle: "width:800px;heigth:400px",
scope: $scope,
templateURL: "views/modals/EditJobModal.html"
});
$q.when(p).then(function (m) {
m.modal('hide');
});
};
var successCallback = function (data, status, headers, config) {
notificationFactory.success();
};
var errorCallback = function (job, status, headers, config) {
notificationFactory.error(job.ExceptionMessage);
};
Move hide modal logic to successCallback function.
I don't know your editable fields on "views/modals/EditJobModal.html" or other pages.
If it is on EditJobModal.html, Better to used two functions, one for create and open modal other for your update logic.
thanks,
Sarath
Update
//Edit Job Modal
$scope.EditJobModal = function (id) {
$.get('/api/apiJob/' + id, function (data) {
console.log(data);
$scope.currentItem = data;
$scope.openEditJobModal = $ekathuwa.modal({
id: "EditJobModal", contentStyle: "width:800px;heigth:400px",
scope: $scope,
templateURL: "views/modals/EditJobModal.html"
});
//show modal window
$scope.openEditJobModal.then(function (m) {
m.modal('show');
});
});
}
//Update Job
$scope.updateJob = function (job) {
console.log($scope.currentItem);
job.JobTypeId = $scope.currentItem.JobType.JobTypeId;
job.JobClassId = $scope.currentItem.JobClass.JobClassId;
job.GeoAreaId = $scope.currentItem.GeoArea.GeoAreaId;
jobFactory.updateJob(job).success(successCallback)
.error(errorCallback);
console.log(job);
};
var successCallback = function (data, status, headers, config) {
//hide modal window
$scope.openEditJobModal.then(function (m) {
m.modal('hide');
});
notificationFactory.success();
};
var errorCallback = function (job, status, headers, config) {
notificationFactory.error(job.ExceptionMessage);
};
Modal
<input type="submit" ng-click="updateJob(currentItem)" value="Submit" />
<input type="button" ng-if="true" data-dismiss="modal" value="Exit" />
Seems to be a bug in AngularUI. See this: https://github.com/angular-ui/bootstrap/issues/1643
The modal scope is not being destroyed correctly on either close or dismiss.

Forcing a ng-src reload

How can I force angularjs to reload an image with an ng-src attribute, when the url of the image has not changed, but its contents has?
<div ng-controller='ctrl'>
<img ng-src="{{urlprofilephoto}}">
</div>
An uploadReplace service that performs a file upload, is replacing the content of the image, but not the url.
app.factory('R4aFact', ['$http', '$q', '$route', '$window', '$rootScope',
function($http, $q, $route, $window, $rootScope) {
return {
uploadReplace: function(imgfile, profileid) {
var xhr = new XMLHttpRequest(),
fd = new FormData(),
d = $q.defer();
fd.append('profileid', profileid);
fd.append('filedata', imgfile);
xhr.onload = function(ev) {
var data = JSON.parse(this.responseText);
$rootScope.$apply(function(){
if (data.status == 'OK') {
d.resolve(data);
} else {
d.reject(data);
}
});
}
xhr.open('post', '/profile/replacePhoto', true)
xhr.send(fd)
return d.promise;
}
}
}]);
When the uploadReplace returns, I don't know how I can force the image to reload
app.controller('ctrl', ['$scope', 'R4aFact', function($scope, R4aFact){
$scope.clickReplace = function() {
R4aFact.uploadReplace($scope.imgfile, $scope.pid).then(function(){
// ?? here I need to force to reload the imgsrc
})
}
}])
An easy workaround is to append a unique timestamp to ng-src to force image reload as follows:
$scope.$apply(function () {
$scope.imageUrl = $scope.imageUrl + '?' + new Date().getTime();
});
or
angular.module('ngSrcDemo', [])
.controller('AppCtrl', ['$scope', function ($scope) {
$scope.app = {
imageUrl: "http://example.com/img.png"
};
var random = (new Date()).toString();
$scope.imageSource = $scope.app.imageUrl + "?cb=" + random;
}]);
Perhaps it could be as simple as adding a decache query string to the image URL? ie.
var imageUrl = 'http://i.imgur.com/SVFyXFX.jpg';
$scope.decachedImageUrl = imageUrl + '?decache=' + Math.random();
This should force it to reload.
An "angular approach" could be creating your own filter to add a random querystring parameter to the image URL.
Something like this:
.filter("randomSrc", function () {
return function (input) {
if (input) {
var sep = input.indexOf("?") != -1 ? "&" : "?";
return input + sep + "r=" + Math.round(Math.random() * 999999);
}
}
})
Then you can use it like this:
<img ng-src="{{yourImageUrl | randomSrc}}" />
Try This
app.controller('ctrl', ['$scope', 'R4aFact', function($scope, R4aFact){
$scope.clickReplace = function() {
R4aFact.uploadReplace($scope.imgfile, $scope.pid).then(function(response){
$scope.urlprofilephoto = response + "?" + new Date().getTime(); //here response is ur image name with path.
});
}
}])
I resorted to make a directive to put random param in the src, but only if the image changes, so I don't mess that much with the caching.
I use it to update the user's profile pic in the navbar when they update it via AJAX, which doesn't happen that often.
(function() {
"use strict";
angular
.module("exampleApp", [])
.directive("eaImgSrc", directiveConstructor);
function directiveConstructor() {
return { link: link };
function link(scope, element, attrs) {
scope.$watch(attrs.eaImgSrc, function(currentSrc, oldSrc) {
if (currentSrc) {
// check currentSrc is not a data url,
// since you can't append a param to that
if (oldSrc && !currentSrc.match(/^data/)) {
setSrc(currentSrc + "?=" + new Date().getTime());
} else {
setSrc(currentSrc);
}
} else {
setSrc(null);
}
})
function setSrc(src) { element[0].src = src; }
}
}
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="exampleApp">
<div>
<img ea-img-src="src"></img>
</div>
<button ng-click="src = 'http://placehold.it/100x100/FF0000'">IMG 1</button>
<button ng-click="src = 'http://placehold.it/100x100/0000FF'">IMG 2</button>
<button ng-click="src = 'http://placehold.it/100x100/00FF00'">IMG 3</button>
</div>

Resources