angular: form submit with dynamic dropdown list - angularjs

I have a small form and in that form i have a drop down list. List items are generated dynamically.
$http({
url: 'alljobs.php',
method: "GET",
params: {
uid: viewer_id
}
}).success(function(data) {
$scope.jobss = data.content;
});
Below is the code for form submit.
$scope.formprofile33 = function() {
var allData33 = {
'msg': $scope.msg,
'emp_id': viewer_id,
'job_id': job.job_id,
'job_title': $scope.jobss.SelectedOption.job_title,
// 'job':job,
'user_id': user_id
}
$http({
method: 'POST',
url: 'send_msg.php',
data: allData33,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).success(function(data) {
if (!data.success) {
$scope.message = data.errors.message;
} else {
$scope.message = '';
alert('Your message has been sent.');
$scope.message = '';
}
});
};
Here is the form.
<form name="formProfile33" method="post" id="formProfile33" role="form" ng-submit="formprofile33()">
<div class="container">
<div class="row">
<div class="col-xs-12">
<div class="row">
<div class="col-xs-10">
<div class="col-xs-12 s_ma">
<select id="job" name="job" class="search_color selectors form-control" ng-model="job" required="required" ng-options="item.job_title for item in jobss track by item.job_id">
<option value=""> Select Job *</option>
</select>
</div>
<textarea name="msg" ng-model="msg" class="form-control textbox1" id="msg" placeholder="Write your message" required="required" rows="3"></textarea>
</div>
</div>
</div>
</div>
<center>
<button type="submit" class="btn btn-home" name="btn-save1" id="btn-save1" required="required"><i class="icon ion-email"></i> Send Message </button>
</center>
</div>
</form>
Problem is i am not able to pass dropdown value and id during form submit.
I am getting below error.
TypeError: Cannot read property 'job_title' of undefined
Please advise how can i submit the form with dropdown id and value.

Your example set a job item to the scope field "job" => ng-model="job",
the full selected item is accessible with $scope.job.
Try $scope.job.job_title or $scope.job.job_id
A print out in your html is anytime a good helper: Full job item: {{job | json}}
https://plnkr.co/edit/VenFVchI0brGZNC2Q7Fn?p=preview

Related

Issue with nested ng-controller in Angularjs

I am stuck with strange issue. Actually I am fetching the data from ajax and showing it on text boxes.
So, basically I have 3 text box (City, City1, City2). By default City textbox is visible rest will show if they have data from Ajax.
User can add city by clicking + button or remove by click on - button.
I am able to fetch and show the data properly on textboxes.
But when I want to add/show City1 or City by clicking on + button. It is simply executing form submit event.
Here is code for Ajax call.
formApp.controller('getprofile', function($scope,$http){
$http({
url: 'get_job_city.php',
method: "GET",
params: {uid: uid}
})
.success(function(data) {
if (data.success) {
$scope.formData.city1 = data.city1;
$scope.formData.city = data.city;
$scope.formData.city2 = data.city2;
}
});
})
Code for form save and show hide city textboxes.
var formApp = angular.module('formApp', []);
formApp.controller('formProfile1', function($scope,$http){
$scope.secondcity1city1 = false;
$scope.thirdcity2 = false;
$scope.hidecity1 = function() { $scope.secondcity1 = false; }
$scope.hidecity2 = function() { $scope.thirdcity2 = false; }
$scope.showcity = function() { $scope.secondcity1 = true; }
$scope.showcity1 = function() { $scope.thirdcity2 = true; }
$scope.formData = {};
$scope.formprofile1 = function() {
$scope.ajaxload = true;
var allData={'formData': $scope.formData, 'uid': uid}
$http({
method : 'POST',
url : 'city_update_exec.php',
data : allData,
headers : { 'Content-Type': 'application/x-www-form-urlencoded' } // set the headers
})
.success(function(data) {
$scope.ajaxload = false;
if (!data.success) {
$scope.errorcity = data.errors.city;
$scope.errorcity1 = data.errors.city1;
$scope.errorcity2 = data.errors.city2;
}else{
alert('City has been updated.');
}
});
};
})
HTML codes are below.
<div class="container" ng-controller="formProfile1">
<form name="formProfile1" method="post" id="formProfile1"
ng-submit="formprofile1()" role="form">
<div ng-controller ="getprofile">
<div id="firstcity">
<div class="col-xs-10">
<div class="topjob_resumetitle" ng-class="{ 'has-error' : errorcity }">
<input name="city" id="city" type="text"
class="form-control textbox1 txt-auto"
required="required" placeholder="Job Location* "
ng-model="formData.city">
<div class = "errorba" ng-show="errorcity">{{errorcity}}
</div>
</div>
</div>
<div class="col-xs-2">
<!--<button class="remove" ng-click="removeChoice()">-</button>-->
</div>
<button class="addfields" ng-click="showcity()">+</button><br>
</div>
<div ng-show="secondcity1">
<div class="col-xs-9"><div class="topjob_resumetitle" ng-class="{ 'has-error' : errorcity1 }">
<input name="city1" id="city1" type="text"
class="form-control textbox1 txt-auto"
placeholder="Job Location* " ng-model="formData.city1">
<div class = "errorba" ng-show="errorcity">{{errorcity1}}
</div>
</div>
</div>
<div class="col-xs-3">
<button class="remove" ng-click="hidecity1()">-</button>
<button class="addfields" ng-click="showcity1()">+</button><br>
</div>
</div>
<div ng-show="thirdcity2">
<div class="col-xs-10"><div class="topjob_resumetitle"
ng-class="{ 'has-error' : errorcity2 }">
<input name="city2" id="city2" type="text"
class="form-control textbox1 txt-auto"
placeholder="Job Location* "
ng-model="formData.city2">
<div class = "errorba" ng-show="errorcity2">{{errorcity2}}
</div>
</div>
</div>
<div class="col-xs-2">
<button class="remove" ng-click="hidecity2()">-</button>
</div>
More text boxes are here
</div>
The problem is that you have not set a type for your buttons, and therefore are defaulting to submit types, which will submit the first parent form found in the DOM when clicked. To allow your custom click handlers to execute properly, change your button types to "button" like so:
<button type="button" class="addfields" ng-click="showcity()">+</button><br>
Remove method="post" and add novalidate on form tag it will stop html5 validation
<form name="formProfile1" novalidate id="formProfile1"
ng-submit="formprofile1()" role="form">
Also if its still not works then change all your button to
<input type="button">//for rest of the buttons
<input type="submit">//for submit button
To make an http request you don't need to use the separate controller. Use factory method in your code for ajax and inject it as a dependency in your controller. Refer Angular Factory method

Cannot pass data to the as.net mvc controller from $http in angularJS

I am Getting null value in action method when i am pass data from angular js to action method. data is coming up to $scope.custmodel and i debug and see it hit to the AddCutomer method but data is null. can anyone help me to fix this issue
Admin.js code
var app = angular.module("adminmdl", [])
app.controller("admincontroller", function ($scope,AdminService) {
$scope.Action = 'Add';
$scope.data = {
cus_code: '',
cus_name: ''
}
$scope.savecu = function () {
AdminService.saveCustomerDdetails($scope.cusmodel).then(function (data) {
if (data != null) {
alert('Insert successfully');
} else {
alert('error in inerting data');
}
});
}
})
.factory("AdminService", function ($http) {
var fact = {};
fact.saveCustomerDdetails = function (d) {
return $http({
url: '/Admin/AddCutomer',
method: 'POST',
data: JSON.stringify(d),
headers: { 'content-type': 'application/json' }
});
};
return fact;
});
ASP MVC Method
[HttpPost]
public JsonResult AddCutomer(Customer customer) {
te.Customers.Add(customer);
te.SaveChanges();
string message = "Success";
return new JsonResult { Data = message, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
html code
<form class="form-horizontal" method="post" action="#" name="basic_validate" id="basic_validate" novalidate="novalidate">
<div class="control-group">
<label class="control-label">Customer Code</label>
<div class="controls">
<input type="text" ng-model="cusmodel.Customercode" name="required" id="required" >
</div>
</div>
<div class="control-group">
<label class="control-label">Customer Name</label>
<div class="controls">
<input type="text" ng-model="cusmodel.Customername" name="name" id="name" >
</div>
</div>
<div class="control-group">
<div class="controls">
<input type="submit" value="Save" ng-click="savecu()" class="btn btn-success">
<input type="submit" value="Clear" class="btn btn-success" />
</div>
</div>
add [FromBody] attribute to the controller as shown below
public JsonResult AddCutomer([FromBody] Customer customer)

value in my array changes but i don't know how to find where it is being changed

So, i have this problem where a property in my array collection changes. Here is the code snippet for my controller:
$http({
method: 'GET',
headers: globalData.httpHeader,
params: {
orderkey:$scope.transaction.orderData.orderkey,
category:'ViewOrderDetail'},
url: globalData.APIARN+ globalData.StageVariable + globalData.OrderRes
}).then(function successCallback(response) {
$ionicLoading.hide();
if (response.data.errorMessage) {
swal({
title: "Ooops!",
text: "Problem Encountered in the Server. Please Contact Support."
});
} else {
$scope.itemDetails =response.data.order.orderdetail;
$scope.items = $scope.itemDetails;
angular.forEach($scope.itemDetails, function(value, key) {
$scope.itemKeys.push(value.productKey);
$scope.itemKey = $scope.itemKeys[$scope.itemKeys.length - 1];
$scope.itemKey++
$scope.itemAmountValues.push(value.quantity * value.unitPrice)
});
}
$scope.calcTotalAndProductAmt();
$scope.showItem = function(selectedKey){
$scope.selectedKeyItems = [];
angular.forEach($scope.itemDetails, function(value, key) {
if(value.itemKey == selectedKey){
$scope.selectedKeyItems.push(value)
}
});
}
console.log("before " + JSON.stringify($scope.items));
$timeout(function(){
console.log("after " + JSON.stringify($scope.items));
})
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
$ionicLoading.hide();
$scope.messageText = globalData.ProblemLoad;
swal({
title: "Ooops!",
text: $scope.messageText
});
}); // $http call
Now, the console log result shows the following:
before [{"id":95,"productKey":"19","productName":"Roast Chicken","quantity":2,"unitPrice":175,"itemStatus":"OPEN"},{"id":96,"productKey":"14","productName":"Bolognese","quantity":3,"unitPrice":225,"itemStatus":"OPEN"},{"id":97,"productKey":"16","productName":"Coke","quantity":4,"unitPrice":50,"itemStatus":"CLOSE"},{"id":98,"productKey":"22","productName":"Rice","quantity":2,"unitPrice":45,"itemStatus":"OPEN"}]
transaction.js:1149
after [{"id":95,"productKey":"19","productName":"Roast Chicken","quantity":2,"unitPrice":175,"itemStatus":"OPEN","$$hashKey":"object:103"},{"id":96,"productKey":"14","productName":"Bolognese","quantity":3,"unitPrice":225,"itemStatus":"OPEN","$$hashKey":"object:104"},{"id":97,"productKey":"16","productName":"Coke","quantity":4,"unitPrice":50,"itemStatus":"OPEN","$$hashKey":"object:105"},{"id":98,"productKey":"22","productName":"Rice","quantity":2,"unitPrice":45,"itemStatus":"OPEN","$$hashKey":"object:106"}]
As you can see, the itemStatus for Coke changes from "CLOSED" to "OPEN". However, i don't know how the value changes since my controller does not have a code that changes this. My html looks like this:
<div class="row" ng-repeat="item in items">
<div class="col col-60" ng-show="item.itemStatus='OPEN'" >
{{item}}
<label class="item item-input">
<select ng-model="item.productKey" ng-change="addPriceEdit(item)" ng-required="true">
<option ng-repeat="item in productskey" value="{{item.productkey}}" >{{item.productname}}</option>
</select>
</label>
</div>
<div class="col col-15">
<label class="item item-input">
<input type="number" ng-model="item.quantity" min="1" step="1" max="9999999999" ng-required="true" ng-change="calcTotalAndProductAmt()">
</label>
</div>
<div class="col col-15">
<label class="item ">
{{item.unitPrice}}
</label>
</div>
<div class="col col-10">
<button class="button button-assertive"
ng-disabled="item.itemStatus!='OPEN'"
ng-click="removeItem($index)">-</button>
</div>
</div>
Anyone has an idea on what's wrong?
Replace your code with -
<div class="col col-60" ng-show="item.itemStatus=='OPEN'" >
Because , with single = , you are assigning value to the variable(so for each object it will change itemstatus to open) . For comparing , you should use ==.

Why will my data not save my updated scope data from my form?

I have created a form in a modal which allows someone to enter in plan details. I have then created the scope form in ng-model attribute as you can see below...
<form>
<div class="form-group">
<label>{{plans.title}}</label>
<input type="text" name="title" ng-model="plans.title" class="form-control" placeholder="Enter Title" required />
</div>
<div class="form-group">
<label>{{plans.overview}}</label>
<textarea name="overview" ng-model="plans.overview" class="form-control" placeholder="Overview/Purpose" required />
</div>
<div class="form-group">
<label>{{plans.notes}}</label>
<textarea name="notes" ng-model="plans.notes" class="form-control" placeholder="Plan Notes" required />
</div>
<div class="form-group">
<label>{{plans.visualplan}}</label>
<div class="button" ngf-select ng-model="plans.visualplan" name="visualplan" ngf-pattern="'image/*'" ngf-accept="'image/*'" ngf-max-size="20MB" ngf-min-height="100" >Upload Visual Plan</div>
</div>
<div class="form-group">
<button type="submit" ng-click="submit()" Value="Post">Post</button>
</div>
</form>
In my code I am then trying to pull the data from the form into my scope object for plans under title, overview, notes and visualplan. Then i have coded this to upload the data from the form into my firebase json. However upon submitting the details, the upload to json process works correctly, but it is uploading the default values for title, overview, notes and visualplan which i have initiatlly set in my dailyplans.js file. What i want to upload is the details which I have attached through ng-model instead of the initial set values. Can anyone spot what I am doing wrong?
Below is my js file.
$scope.submit = function() {
$scope.plans = {
title: 'title',
overview: 'overview',
notes: 'notes',
visualplan: 'visual plan'
}
if (authData) {
ref.child('teaching-plans').child('teaching-plans' + authData.uid).set($scope.plans).then(function(authdata) {
console.log('successful');
}).catch(function(error) {
console.log(error);
});
}
}
You are resetting the plans object when user clicks on submit. Ideally it should be outside of submit method.
This is how you should do it
$scope.plans = {
title: 'title',
overview: 'overview',
notes: 'notes',
visualplan: 'visual plan'
}
$scope.submit = function(plans) {
if (authData) {
ref.child('teaching-plans').child('teaching-plans' + authData.uid).set(plans).then(function(authdata) {
console.log('successful');
}).catch(function(error) {
console.log(error);
});
}
}
And also update the html as
<div class="form-group">
<button type="submit" ng-click="submit(plans)" Value="Post">Post</button>
</div>
Hope this helps.
Just don't overwrite your plans object:
$scope.submit = function() {
$scope.plans.title = 'title';
$scope.plans.overview = 'overview';
$scope.plans.notes = 'notes';
$scope.plans.visualplan = 'visual plan;
if (authData) {
ref.child('teaching-plans').child('teaching-plans' + authData.uid).set($scope.plans).then(function(authdata) {
console.log('successful');
}).catch(function(error) {
console.log(error);
});
}
}
This way angular can fire the listeners correctly.

Sharepoint 2013 App AngularJS: lookup field causing error when adding to list "A type named 'SP.Data.TeamsListItem' could not be resolved by the model

I have a Players List with a lookup field for Team Name linked to the Teams List.
When trying to add or update the Players List I am getting the error
"A type named 'SP.Data.TeamsListItem' could not be resolved by the model. When a model is available, each type name must resolve to a valid type.".
The guid for the players list is '16a03b71-07ea-49c4-ab14-419b51047119'.
The guid for the teams list is '2a2916c2-22fb-4588-bca1-83479a4d85b2'.
This is the contents of data field when the error occurs:
<pre>
"{\"__metadata\":{\"type\":\"SP.Data.PlayersListItem\"},\"Title\":\"Bill\",\"PlayerPosition\":\"Goalie\",\"Birthdate\":\"2/21/1999\",\"TeamName\":{\"__metadata\":{\"id\":\"Web/Lists(guid'2a2916c2-22fb-4588-bca1-83479a4d85b2')/Items(1)\",\"uri\":\"https://app-2971fdcf9ede6a.rawtecapps.com/sites/raiders/AngularCRM/_api/Web/Lists(guid'2a2916c2-22fb-4588-bca1-83479a4d85b2')/Items(1)\",\"etag\":\"\\\"1\\\"\",\"type\":\"SP.Data.TeamsListItem\"},\"Id\":1,\"Title\":\"aa\",\"ID\":1,\"$$hashKey\":\"object:176\"},\"Season\":\"2015\"}"
</pre>
Definition of my Lookup field.
<pre>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Field
ID="{7853bbf2-9fd7-4f85-aca8-269d8f967650}"
Name="TeamName"
DisplayName="Team Name"
Type="Lookup"
List="Lists/Teams"
ShowField="Title"
Required="FALSE"
Group="Custom Site Columns">
</Field>
</Elements>
</pre>
Content Type for Teams List:
<pre>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/"><ContentType ID="0x0100A379177A3533447D9B6546708F7DFD2D" Name="Teams" Group="Custom Content Types" Description="Teams Content Type" Inherits="FALSE" Version="0">
<FieldRefs>
<FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" DisplayName="Team Name" Required="TRUE" Name="Title" />
<FieldRef ID="{fce82853-3f44-4cc9-8f71-eb6506be0e9e}" DisplayName="Team City" Required="FALSE" Name="TeamCity" />
</FieldRefs>
</ContentType>
</pre>
playersnew.html page:
<pre>
<div class="form-horizontal">
<fieldset>
<div class="form-group">
<label for="txtID" class="col-lg-2 control-label">ID:</label>
<div class="col-lg-6">
<input id="txtID" type="text" readonly class="form-control" ng-model="player.ID">
</div>
</div>
<div class="form-group">
<label for="txtPlayerName" class="col-lg-2 control-label">Player Name:</label>
<div class="col-lg-6">
<input id="txtPlayerName" type="text" class="form-control" ng-model="player.Title">
</div>
</div>
<div class="form-group">
<label for="txtPlayerPosition" class="col-lg-2 control-label">Player Position:</label>
<div class="col-lg-6">
<input id="txtPlayerPosition" type="text" class="form-control" ng-model="player.PlayerPosition">
</div>
</div>
<div class="form-group">
<label for="txtBirthdate" class="col-lg-2 control-label">Birthdate:</label>
<div class="col-lg-6">
<input id="txtBirthdate" type="text" class="form-control" ng-model="player.Birthdate">
</div>
</div>
<div class="form-group">
<label for="txtTeamName" class="col-lg-2 control-label">Team Name:</label>
<div class="col-lg-6" ng-controller="TeamDropDownController">
<select name="teams" ng-model="player.TeamName" ng-options="team.Title for team in teams">
<option ng-repeat="team in teams" value="{{team.Id}}">{{team.Title}}</option>
</select>
</div>
</div>
<div class="form-group">
<label for="txtSeason" class="col-lg-2 control-label">Season:</label>
<div class="col-lg-6">
<input id="txtSeason" type="text" class="form-control" ng-model="player.Season">
</div>
</div>
<div class="form-group">
<div class="col-lg-offset-2">
<input id="cmdSave" type="button" class="button" value="Save" data-ng-click="addPlayer()" />
</div>
</div>
</pre>
Angular JS (playersnew Controller):
><pre>
app.controller('playersnewController',
function ($scope, $location, wingtipCrmService) {
$scope.player = {};
$scope.player.Title = "";
$scope.player.PlayerPosition = "";
$scope.player.Birthdate = "";
$scope.player.TeamName = "";
$scope.player.TeamName.Id = "";
$scope.player.TeamName.Title = "";
$scope.player.Season = "";
$scope.addPlayer = function () {
var playerName = $scope.player.Title;
var playerPosition = $scope.player.PlayerPosition;
var birthdate = $scope.player.Birthdate;
var teamName = $scope.player.TeamName;
var teamNameId = $scope.player.TeamName.Id;
var teamNameTitle = $scope.player.TeamName.Title;
var season = $scope.player.Season;
wingtipCrmService.addPlayer(playerName, playerPosition, birthdate, teamName, teamNameId, teamNameTitle ,season)
.success(function (data) {
$location.path("/playershome");
});
}
} );
</pre>
Angular JS (service for addplayer):
> <pre>
service.addPlayer = function (PlayerName,PlayerPosition,Birthdate,TeamName,TeamNameId,TeamNameTitle,Season) {
var restQueryUrl = "../_api/web/lists/getByTitle('Players')/items";
var playerData = {
__metadata: { "type": "SP.Data.PlayersListItem" },
Title: PlayerName,
PlayerPosition: PlayerPosition,
Birthdate: Birthdate,
TeamName: TeamName,
Season: Season
};
var requestBody = JSON.stringify(playerData);
return $http({
method: 'POST',
url: restQueryUrl,
contentType: "application/json;odata=verbose",
data: requestBody,
headers: {
"Accept": "application/json; odata=verbose",
"X-RequestDigest": requestDigest,
"content-type": "application/json;odata=verbose"
}
});
}
</pre>
Angular JS (TeamDropDownController and service):
<pre>
app.controller('TeamDropDownController',
function ($scope, wingtipCrmService) {
wingtipCrmService.getDropDownTeams().success(function (data) {
$scope.teams = data.d.results;
})
});
</pre>
<pre>
service.getDropDownTeams = function () {
var restQueryUrl = "../_api/web/lists/getByTitle('Teams')/items/" +
"?$select=ID,Title";
return $http({
method: 'GET',
url: restQueryUrl,
headers: { "Accept": "application/json; odata=verbose" }
})
}
</pre>
I am new to developing sharepoint apps and Angular JS. I have been trying to figure out a solution for this issue for over a week and in the process I have learned a great deal.
I am using TeamDropDownController to load the select statement with team names and then using playersnewcontroller to add new player record.
The add player javascript works until I added the code to include the TeamName field. I am afraid that the way I am loading the dropdown with a controller is causing a problem with the playersnewController.
The error message:
"A type named '{ListItemEntityTypeFullName}' could not be resolved by the
model. When a model is available, each type name must resolve to a
valid type.".
commonly occurs when List Item entity with the specified name could not be found. In your case it means there is no entity with name SP.Data.PlayersListItem.
The following endpoint allows to properly determine list item entity name:
Uri: /_api/lists/getbytitle('{List Title}')?$select=ListItemEntityTypeFullName
Method: GET
The following jQuery example demonstrates how to dynamically determine entity type name while creating list item:
function createListItem(webUrl,listTitle,itemProperties)
{
var requestUri = webUrl + "/_api/lists/getbytitle('" + listTitle + "')?$select=ListItemEntityTypeFullName";
return executeJson({url:requestUri}).then(function(data){
var requestUri = webUrl + "/_api/web/lists/getbytitle('" + listTitle + "')/items";
itemProperties['__metadata'] = {'type': data.d.ListItemEntityTypeFullName};
return executeJson({url: requestUri, method: 'POST', data: itemProperties});
});
}
var properties = {'Title':'John Doe'};
createListItem(_spPageContextInfo.webAbsoluteUrl,'Contacts',properties)
.done(function(data)
{
console.log('List item has been created');
})
.fail(function(error){
console.log(JSON.stringify(error));
});
where
function executeJson(options)
{
method = options.method || 'GET';
headers = options.headers || {};
headers["Accept"] = "application/json;odata=verbose";
if(method == "POST") {
headers["X-RequestDigest"] = $("#__REQUESTDIGEST").val();
}
var ajaxOptions =
{
url: options.url,
type: method,
contentType: "application/json;odata=verbose",
headers: headers
};
if (typeof options.data != 'undefined') {
ajaxOptions.data = JSON.stringify(options.data);
}
return $.ajax(ajaxOptions);
}
To fix my issue I added the player record without filling the TeamName lookup field. Then immediately performed an update of the player record with the TeamName field information.

Resources