Cannot read property in angular js - javascript

This is my script file
app.controller('userController', function PostController($scope, userFactory) {
$scope.users = [];
$scope.user = { items : [] };
$scope.editMode = false;
$scope.addItem = function () {
$scope.user.items.push({
Name: $scope.newItemName,
Value: $scope.newItemValue
});
};
$scope.deleteItem = function (index) {
$scope.user.items.splice(index, 1);
};}
This is my html file.
<div class="form-group">
<ul class="nav">
<label for="title" class="col-sm-2 control-label">Items</label>
<div class="col-sm-10">
<input type="text" value="ItemName" class="form-control" id="title" ng-model="newItemName" required placeholder="name of new item...">
<input type="text" value="ItemName" class="form-control" id="title" ng-model="newItemValue" required placeholder="name of new item...">
</div>
<button ng-click="addItem()">Add Me</button>
<li ng-repeat="item in user.items">
{{item.Name}} <a ng-click="deleteItem($index)" class="delete-item">x</a>
</li>
</ul>
</div>
When I Click add me button i get an error as
TypeError: Cannot read property 'items' of undefined
I cant figure out the error and why it occurs. Please help me I'm new to angular js

The error occurs because your user property is null:
$scope.user = null;
Change it to an actual object which ideally has items property:
$scope.user = { items : [] };

Simple where is items if you have $scope.user = null;
so simple do one thing add
$scope.user = {items:[]};
and then use $scope.user.items.push(data)

Related

Uncaught ReferenceError: Unable to process binding with KnockoutJS

We have a multiple page form like below , each page on the form is associated with different model classes. I am trying use the value the users selected in Page 1 and based upon that value selected in Pg1 I need to show/hide the field in Page2.
Page2 has a button which allows the users add courses, when they click on the button few fields shows up in the page in foreach loop and one of the field should show/hide based on the selection made on the previous page. But the above logic throws error like Uncaught ReferenceError: Unable to process binding "visible:" below is the viewmodel
How can I have the binding work properly here and get rid of the error
It's case sensitive. Also, the foreach loop changes the binding context, so you need to do this:
<div class="form-group required" data-bind="visible: $parent.Solution() == 'Other'">
Edit- that is, if you're indeed trying to reference the Solution property from the parent viewmodel. It's not clear from your example wheter a CoursesList item also has such a property.
Just expanding on #Brother Woodrow's answer with an very basic runnable example might help with things.
function ViewModel() {
var self = this;
self.pages = [1, 2]
self.currentPage = ko.observable(1)
self.solutions = ko.observableArray(['Solution 1', 'Solutions 2', 'Other']);
self.solution = ko.observable().extend({
required: {
params: true,
message: "Required"
}
});
self.next = function() {
self.currentPage(self.currentPage() + 1);
};
self.back = function() {
self.currentPage(self.currentPage() - 1);
};
self.CourseDetails = ko.observableArray();
self.addCourse = function() {
self.CourseDetails.push(new coursesList());
}
self.pageVisible = function(page) {
return self.currentPage() == page;
}
}
function coursesList() {
var self = this;
self.otherSolution = ko.observable().extend({
required: {
params: true,
message: "Required"
}
});
}
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div id="Page_1" data-bind="visible: pageVisible(1)">
<h2>Page 1</h2>
<div class="form-group required">
<label for="Solution" class="control-label">Solution</label>
<select id="Solution" name="Solution" class="form-control" data-bind="options: solutions, value: solution, optionsCaption: 'Select'"></select>
</div>
<button type="submit" id="NtPg" class="SubmitButton" data-bind="click: next">Next</button>
</div>
<div id="Page_2" data-bind="visible: pageVisible(2)">
<h2>Page 2</h2>
<button type="submit" id="AddCourseInfo" class="SubmitButton" data-bind="click: addCourse">Add Course Info</button>
<div data-bind="foreach:CourseDetails">
<div class="form-group required" data-bind="visible: $parent.solution() == 'Other'">
<label for="OtherSolution" class="control-label">Explain Other Solution : </label>
<input type="text" maxlength="1000" id="OtherSolution" name="OtherSolution" class="form-control" data-bind="value : otherSolution" required/>
</div>
</div>
<button type="submit" id="NtPg" class="SubmitButton" data-bind="click: back">Back</button>
</div>
<pre data-bind="text: ko.toJSON($root)"></pre>

How to send Javascript array as Json combined with a html form?

I am creating a restaurant menu app that a waiter can use to input orders.
I have a Js array called itemOrderList that I am storing item names in. I want to be able to send that list of item names as Json array with customer name form input field and item price to back end to be stored in my DB. I am having issues going about doing this. What should I do? Google dev tools says "ReferenceError: itemOrderList is not defined" where I am trying to stringify the Js array.
AngularJs code
.controller('orderAddCtrl', ['$scope', '$location', 'dataService', function ($scope, $location, dataService) {
$scope.itemOrderList = [];
$scope.totalItemPrices = 0;
$scope.addOrderToList = function (item) {
console.log(item.itemName);
$scope.addPricesToTotalItemPrices(item.itemPrice);
$scope.itemOrderList.push(item.itemName);
};
$scope.addPricesToTotalItemPrices = function (price) {
console.log(price);
$scope.totalItemPrices += price ;
};
$scope.removeFromOrderToList = function (index) {
console.log(index);
$scope.itemOrderList.splice(index, 1);
};
$scope.createOrder = function (order) {
var myJson = JSON.stringify(itemOrderList);
order.orderPrice = totalItemPrices;
order.orderItems = myJson;
dataService.addOrder(order).then(function () {
$location.path('/');
});
};
Html
<form class="form-horizontal" ng-init="getItems()">
<div class="row">
<div class="col-6">
<div class="form-group">
<div>
<input ng-click="createOrder(order)" class="btn btn-success" value="Create" />
Back
</div>
</div>
</div>
<div class="col-6">
<div class="form-group">
<label class="control-label">Customer Name</label>
<div class="col-lg-10">
<input type="text" class="form-control" ng-model="order.customerName" />
</div>
</div>
</div>
</div>
<div>
<h1>Total Price: ${{totalItemPrices}}</h1>
</div>
<div class="">
<h2>Food Items</h2>
<div class="row">
<button class="btn btn-success col-3" ng-repeat="i in Items" ng-click="addOrderToList(i)">{{i.itemName}}</button>
</div>
</div>
<div class="">
<h2>Order Items</h2>
<ul>
<li ng-repeat="i in itemOrderList track by $index">
<p>{{i}}/<p>
<button ng-click="removeFromOrderToList($index)">Remove</button>
</li>
</ul>
</div>
</div>
</form>
I bet you need to specify you're using vars declared in $scope as so...
$scope.createOrder = function (order) {
var myJson = JSON.stringify($scope.itemOrderList);
order.orderPrice = $scope.totalItemPrices;
order.orderItems = myJson;
dataService.addOrder(order).then(function () {
$location.path('/');
});
};

Add items to list in angular

I have the following to create a job with a position and multiple requirements Plunker example:
<div ng-controller="MainCtrl as vm">
<div>Position: <span data-ng-bind="vm.job.position"></span></div>
<br/>
<form name="form" data-ng-submit="vm.create(job)">
<label for="position">Enter the Position</label>
<input id="position" name="vm.job.position" type="text" data-ng-model="vm.job.position" />
<div>
<br/>
Requirements:
<br/>
<ul>
<li data-ng-repeat="r in vm.job.requirements">{{r.name}}</li>
</ul>
<input id="name" name="requirement.name" type="text" data-ng-model="requirement.name" />
<input type="button" value="Add Requirement" class="button" data-ng-click="vm.addRequirement(requirement)"/>
</div>
<br/><br/>
<button>Create Job</button>
</form>
</div>
the controller
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
var vm = this;
vm.job = { position: '', requirements: [] };
vm.create = function (job) {
alert("job created");
}
vm.addRequirement = function (requirement) {
vm.job.requirements.push(requirement);
}
});
When I add a requirement I see it on the list but when I try to add a new one, the one that is already in the list start to change. I do not want that. I want to add a new one to the list.
Finally, when I submit the form using "Create Job" is where I will send all the Job data to the API.
The problem is with your addRequirement function, because you are adding the same object to the list (and that's the reason your item changes the name when you edit the input box).
To make your example work as intended you should push a clone of the requirement object (see documentation).
vm.addRequirement = function (requirement) {
vm.job.requirements.push( angular.copy(requirement) );
}
The easiest way to do this, is simply use ng-model on the input that you would like to append to your list. Then you can easily access it from the controller.
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
var vm = this;
vm.job = { position: '', requirements: [] };
function create(job) {
alert("job created");
}
function addRequirement() {
vm.job.requirements.push(vm.currentRequirement);
}
vm.create = create;
vm.addRequirement = addRequirement;
});
and in the html:
<input type="button" value="Add Requirement" ng-click="vm.addRequirement()"/>

Angular - Form Validation - Cannot read property 'name' of undefined

so I have a form with an input and some other stuff and I'm trying to do some angular validation to make sure that the entered information is actually there (not blank). To do so, I'm using an if statement.
The error message I get is:
Cannot read property 'name' of undefined
It seems as if it can't read an <input> tag name if it's left blank. The function works when I fill in the , but not the others (which are a and . I'm just trying to use an if statement to see if they've been filled out. Here's the html and angular code below:
reviewModal.view.html (shortened form version)
<div class="modal-content">
<div role="alert" ng-show="vm.formError" class="alert alert-danger">{{ vm.formError }}</div>
<form id="addReview" name="addReview" role="form" ng-submit="vm.onSubmit()" class="form-horizontal">
<label for"name" class="col-xs-2 col-sm-2 control-label">Name</label>
<div class="col-xs-10 col-sm-10">
<input id="name" name="name" ng-model="vm.formData.name" class="form-control">
</div>
<button type="submit" class="btn btn-primary">Submit review</button>
</form>
</div>
reviewModal.controller.js
(function() {
angular
.module('loc8rApp')
.controller('reviewModalCtrl', reviewModalCtrl);
reviewModalCtrl.$inject = ['$uibModalInstance', 'locationData'];
function reviewModalCtrl($uibModalInstance, locationData) {
var vm = this;
vm.locationData = locationData;
vm.onSubmit = function() {
vm.formError = "";
if(!vm.formData.name || !vm.formData.rating || !vm.formData.reviewText) {
vm.formError = "All fields required, please try again";
return false;
} else {
console.log(vm.formData);
return false;
}
};
vm.modal = {
cancel : function() {
$uibModalInstance.dismiss('cancel');
}
};
}
})();
locationDetail.controller.js
(function() {
angular
.module('loc8rApp')
.controller('locationDetailCtrl', locationDetailCtrl);
locationDetailCtrl.$inject = ['$routeParams', '$uibModal', 'loc8rData'];
function locationDetailCtrl($routeParams, $uibModal, loc8rData) {
var vm = this;
vm.locationid = $routeParams.locationid;
loc8rData.locationById(vm.locationid)
.success(function(data) {
vm.data = { location: data };
vm.pageHeader = {
title: vm.data.location.name
};
})
.error(function(e) {
console.log(e);
});
vm.popupReviewForm = function() {
var modalInstance = $uibModal.open({
templateUrl: '/reviewModal/reviewModal.view.html',
controller: 'reviewModalCtrl as vm',
resolve : {
locationData : function() {
return {
locationid : vm.locationid,
locationName : vm.data.location.name
};
}
}
});
};
}
})();
vm.formData must be defined before you can assigned/read name property in the html. Update code in reviewModalCtrl to init vm.formData:
vm.formData = {};
Use angular validation instated validating things in controller as follows.
<div class="modal-content">
<div role="alert" ng-show="addReview.$submitted && addReview.$invalid" class="alert alert-danger">All fields required, please try again</div>
<form id="addReview" name="addReview" role="form" ng-submit="vm.onSubmit()" class="form-horizontal">
<label for"name" class="col-xs-2 col-sm-2 control-label">Name</label>
<div class="col-xs-10 col-sm-10">
<input id="name" name="name" ng-model="vm.formData.name" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary">Submit review</button>
</form>
</div>
I have used required in text box and show the error message on top with
ng-show="addReview.$invalid"
You do not need any code on controller.

Angular TypeError: Cannot read property 'icon' of undefined

how to handle empty input on angular?
I want validate on back end not on front end. But when i submit it return me error if i let it blank on icon input
TypeError: Cannot read property 'icon' of undefined
Here is my form:
<div class="form-group">
<div class="form-material form-material-danger">
<input class="form-control" type="text" id="name" ng-model="menu.name" placeholder="Menu Name.." empty-to-null>
<label for="name">Name</label>
</div>
</div>
<div class="form-group">
<div class="form-material form-material-danger">
<input class="form-control" type="text" id="icon" ng-model="menu.icon" placeholder="Menu Icon.." >
<label for="icon">Icon</label>
</div>
</div>
Here is my code:
var data = {
icon: $scope.menu.icon,
name: $scope.menu.name
};
AdminMenu.save(data, function (response) {
console.log(response);
$scope.menu = null;
ResultService(response);
$scope.dtInstance.reloadData();
}, function (response) {
ResultService(response.data);
})
.$promise.finally(function () {
$scope.button_text = "Store";
$scope.loading = false;
});
$scope.menu = null
When you set menu to null, angular can't find menu.icon anymore. You should do $scope.menu = {} if you want to "reset" it.
And, of course, don't forget to initialize $scope.menu before using it.

Categories

Resources