AngularJS - To Do App Place Submit and Delete Function into Factories - javascript

I've created a simple To Do App and while working on it I felt like I will end up placing too much code into my Controller and will eventually get messy and hard to read. I want to know how can I move my functions into factories so that my code can look somewhat cleaner.
Here is my JS:
angular.module('toDoApp', [])
.controller('toDoCtrl', function($scope){
//set $scope variables
$scope.tasks = [];
$scope.submitTask = function(){
$scope.tasks.unshift($scope.enteredTask);
$scope.enteredTask = '';
};
$scope.removeTask = function(task) {
var i = $scope.tasks.indexOf(task);
$scope.tasks.splice(i, 1);
};
})
.factory('toDoFactory', ['$http', function($http){
return function(newTask) {
};
}])
Here is the HTML if needed:
<form ng-submit="submitTask()">
<!-- task input with submit button -->
<label>Task: </label>
<input type="text" placeholder="Enter Task" ng-model="enteredTask" required>
<button>Submit</button>
</form>
<div>
<!-- create unordered list for task that are submitted
need check boxes -->
<ul>
<li ng-repeat="task in tasks">
{{ task }}
<button ng-click="removeTask()">x</button>
</li>
</ul>
</div>
As you can see I kinda started the factory but just don't know how to go about it.
Any suggestions will be greatly appreciated.

You will need to inject your factory inside controller and then use the methods defined in the factory from the controller:
angular.module('toDoApp', [])
.controller('toDoCtrl', function($scope, toDoFactory){
//set $scope variables
$scope.tasks = [];
$scope.submitTask = function(){
toDofactory.submittask(); //Just for demo.Passin your parameters based on your implementation
};
$scope.removeTask = function(task) {
var i = $scope.tasks.indexOf(task);
$scope.tasks.splice(i, 1);
};
})
.factory('toDoFactory', ['$http', function($http){
var methods = {};
methods.submittask = function(){
//your logic here
};
methods.removetask = function(){
//your logic here
}
return methods;
}])

var app = angular.module('toDoApp', []);
app.controller('toDoCtrl', function($scope, toDoFactory){
$scope.tasks = [];
toDoFactory.get = function(){
}
toDoFactory.delete = function(){
}
toDoFactory.update = function(){
}
});
app.factory('toDoFactory', ['$http', function($http){
var todo = {};
todo.get = function(){
};
todo.delete = function(){
};
todo.update = function(){
}
return todo;
}]);
This is simple architecture, you can add more logic,
Make sure you know about dependency injection(DI)

Here is the answer for those that want to see what the end result will look like when all the code is plugged in. Thanks again for the answers as it was able to guide me in the right direction.
.controller('toDoCtrl', function($scope, toDoFactory){
$scope.tasks = toDoFactory.tasks;
$scope.submitTask = function(){
toDoFactory.submitTask($scope.enteredTask);
$scope.enteredTask = '';
};
$scope.removeTask = function(task) {
toDoFactory.removeTask();
};
})
.factory('toDoFactory', ['$http', function($http){
var toDo = {
tasks: [],
enteredTask: '',
submitTask: function(task){
toDo.tasks.unshift(task);
},
removeTask: function(task) {
var i = toDo.tasks.indexOf(task);
toDo.tasks.splice(i, 1);
}
};
}])

Related

ng-change is not firing when changing value from service

I need to reflect some changes to controller B (inside some event) when I make change at controller A. For that I am using a service.
When I am changing service value from FirstCtrl, ng-change is not firing at SecondCtrl. Is there anything I have missed or need to change?
Please note that I am using angular 1.5.6. and don't want to use watch or even scope.
Below is my code.
var myApp = angular.module('myApp', []);
myApp.factory('Data', function() {
return {
FirstName: ''
};
});
myApp.controller('FirstCtrl', ['Data',
function(Data) {
var self = this;
debugger
self.changeM = function() {
debugger
Data.FirstName = self.FirstName;
};
}
]);
myApp.controller('SecondCtrl', ['Data',
function(Data) {
var self = this;
self.FirstName = Data;
self.changeM = function() {
alert(1);
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="FirstCtrl as c">
<input type="text" ng-model="c.FirstName" data-ng-change="c.changeM()">
<br>Input is : <strong>{{c.FirstName}}</strong>
<div ng-controller="SecondCtrl as c1">
Input should also be here: {{c1.FirstName}}
<input type="text" ng-model="c1.FirstName" data-ng-change="c1.changeM()">
</div>
</div>
<hr>
</div>
As you dont want to use $scope trying modifying the code in order to use $emit and $on feature in angular js to communicate between two controllers. You can refer this link.
var myApp = angular.module('myApp', []);
myApp.factory('Data', function() {
return {
FirstName: ''
};
});
myApp.controller('FirstCtrl', ['Data',
function(Data) {
var self = this;
debugger
self.changeM = function() {
debugger
//Data.FirstName = self.FirstName;
Data.$on('emitData',function(event,args){
Data.FirstName=args.message
document.write(Data.FirstName)
})
};
}
]);
myApp.controller('SecondCtrl', ['Data',
function(Data) {
var self = this;
self.FirstName = Data;
self.changeM = function() {
Data.$emit('emitData',{
message:Data.FirstName
})
};
}
]);
The only way then is to directly copy the reference of the data object within the controller. Note that you don't need ng-change to update the value then.
If you want something else, either wrap the FirstName in a sub object of Data and do the same i did :
Data = {foo:'FirstName'};
Or use $watch since it's the whole purpose of that function.
Here is a working code with copying the Data object in the controller.
var myApp = angular.module('myApp', []);
myApp.factory('Data', function() {
return {
FirstName: ''
};
});
myApp.controller('FirstCtrl', ['Data',
function(Data) {
var self = this;
self.Data=Data;
debugger
self.changeM = function() {
debugger
};
}
]);
myApp.controller('SecondCtrl', ['Data',
function(Data) {
var self = this;
self.Data = Data;
self.changeM = function() {
alert(1);
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="FirstCtrl as c">
<input type="text" ng-model="c.Data.FirstName" data-ng-change="c.changeM()">
<br>Input is : <strong>{{c.Data.FirstName}}</strong>
<div ng-controller="SecondCtrl as c1">
Input should also be here: {{c1.Data.FirstName}}
<input type="text" ng-model="c1.Data.FirstName" data-ng-change="c1.changeM()">
</div>
</div>
<hr>
</div>
The only way I know to solve the problem is using watch, unfortunately. (I am new to angular.)
From the ngChange document (https://docs.angularjs.org/api/ng/directive/ngChange):
The ngChange expression is only evaluated when a change in the input value causes a new value to be committed to the model.
It will not be evaluated:
if the value returned from the $parsers transformation pipeline has not changed
if the input has continued to be invalid since the model will stay null
**if the model is changed programmatically and not by a change to the input value**

Angular service with different angular app

Here i am using angular service.In my case i am getting value for first app but not for second .please help me .
thank you.
here is my html:-
<div ng-app="mainApp" ng-controller="CalcController">
<p>Enter a number: <input type="number" ng-model="number" />
<button ng-click="multiply()">X<sup>2</sup></button>
<p>Result: {{result}}</p>
</div>
<div ng-app="myApp2" ng-controller="myController2">
<p>Enter a number: <input type="number" ng-model="numberSecond" />
<button ng-click="multiplyValue()">X<sup>2</sup></button>
<p>Result: {{result2}}</p>
</div>
here is js:-
angular.module('myReuseableMod',[]).factory('$myReuseableSrvc',function()
{
// code here
var factory = {};
factory.multiply = function(a)
{
return a * a
}
return factory;
});
var mainApp = angular.module("mainApp", ['myReuseableMod']);
mainApp.controller('CalcController',['$scope', '$myReuseableSrvc',function($scope, $myReuseableSrvc) {
alert("inside controller");
$scope.multiply = function()
{
alert("hello1");
$scope.result = $myReuseableSrvc.multiply($scope.number);
}
}]);
var mainApp2 = angular.module("myApp2", ['myReuseableMod']);
mainApp.controller('myController2',['$scope', '$myReuseableSrvc',function($scope, $myReuseableSrvc) {
alert("inside controller");
$scope.multiplyValue = function()
{
alert("hello1");
$scope.result2 = $myReuseableSrvc.multiply($scope.numberSecond);
}
}]);
Your 'myController2' is in the wrong app
mainApp.controller('myController2'
Should be:
mainApp2.controller('myController2'
EDIT:
Ah yes I see the problem. You cannot use ng-app twice like that. If you want what you are trying to achieve which is multiple applications you have to 'bootstrap' the second one:
plunk here:
http://plnkr.co/edit/qfllLO9uy6bC5OLkHnYZ?p=preview
angular.module('myReuseableMod',[]).factory('$myReuseableSrvc',function() {
var factory = {};
factory.multiply = function(a) {
return a * a
}
return factory;
});
var mainApp = angular.module("mainApp", ["myReuseableMod"]);
mainApp.controller('CalcController', ['$scope', '$myReuseableSrvc',function($scope, $myReuseableSrvc) {
$scope.multiply = function() {
$scope.result = $myReuseableSrvc.multiply($scope.number);
}
}]);
var mainApp2 = angular.module("mainApp2", []);
mainApp2.controller("MyController2", function($scope, $myReuseableSrvc) {
console.log('init B');
$scope.multiplyValue = function() {
$scope.result2 = $myReuseableSrvc.multiply($scope.numberSecond);
}
});
angular.element(document).ready(function() {
angular.bootstrap(document.getElementById("myDiv2"), ["mainApp2", "myReuseableMod"]);
});
This is a good post to read:
http://www.simplygoodcode.com/2014/04/angularjs-getting-around-ngapp-limitations-with-ngmodule/

My ng-model is not updating first time

i am having a problem with ng-model .When i am adding tag from suggestion list its not updating model value until i am not deleting tags and adding again.In my project its working fine but for plunker only its happening.Please check this out and help me..
thank you..
Here is my html:-
<tags-input ng-model="tags2" display-property="tagName" on-tag-added="getTags()" id="target">
<auto-complete source="loadTags($query)" min-length="2"></auto-complete>
</tags-input>
<p>{{tags2}}</p>
Here is my js:-
var app = angular.module('myApp', ['ngTagsInput', 'ui.bootstrap']);
app.controller(
'myController',
function($scope, $http) {
$scope.tagsValues =[];
$scope.loadTags = function(query) {
return $http.get('tags.json');
};
$scope.getTags = function() {
$scope.tagsValues = $scope.tags2.map(function(tag) {
return tag.tagId;
});
alert(" Tag id is :"+ $scope.tagsValues);
};
});
Here is my plunker:-
http://plnkr.co/edit/6Mr2qk2S2RvGJLevf2UI?p=preview
All you have to do to make this work, is define and initialize the variable $scope.tags2 first:
var app = angular.module('myApp', ['ngTagsInput', 'ui.bootstrap']);
app.controller(
'myController',
function($scope, $http) {
$scope.tagsValues = '';
$scope.tags2 = [];
$scope.loadTags = function(query) {
return $http.get('tags.json');
};
$scope.getTags = function() {
$scope.tagsValues = $scope.tags2.map(function(tag) {
return tag.tagId;
});
alert(" Tag id is :"+ $scope.tagsValues);
};
});
See my plunker: http://plnkr.co/edit/Y3f8kLBnexOXg5gwmldL?p=preview

Need help with simple angularjs programming

I am trying to do simple programming in angularjs. I have created two buttons. The first button has text "clickHere", and the second has no text. My task is when I click the button that has text, it will automatically get empty and the second button will have the same text. (and vice versa).
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.name = 'Superhero';
$scope.name1 = '';
var val = 'Hello';
$scope.click0 = function() {
//alert("hello!");
$scope.name = $scope.name1;
$scope.name1="";
//return val;
};
$scope.click1 = function() {
//alert("hello!");
$scope.name1 = $scope.name;
$scope.name="";
// return val;
};
}
<body ng-app="myApp">
<div ng-controller="MyCtrl">
<button ng-click="click0()" >{{name}}</button>
<button ng-click="click1()" >{{name1}}</button>
</div>
</body>
Here is my code in jsfiddle. http://jsfiddle.net/simpleorchid/a65zV/
I think your issue was you were overwriting your stored value. I added a $scope variable called word, and now it works:
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.word = 'Superhero';
$scope.name = $scope.word;
$scope.name1 = '';
$scope.click0 = function() {
$scope.name1 = $scope.word;
$scope.name="";
};
$scope.click1 = function() {
$scope.name = $scope.word;
$scope.name1="";
};
}
Udpated Fiddle: http://jsfiddle.net/pWjLR/1/
Just replace the click1() with click0() like in the JSFiddle here and everything will work just as you want it to.

Controller hiding $scope.var in another controller with angular

I have 2 controllers. I want to make a simple toggle where if a function is called it hides code in the other controller. Here is what I have...
Angular:
var app = angular.module('plunker', []);
app.factory('data', function () {
var fac = [];
fac.hideIt = function (hide) {
console.log(hide)
if (hide != null)
return true;
else
return false;
};
return fac;
});
app.controller('MainCtrl', function($scope, data) {
$scope.name = 'World';
console.log(data.hideIt()); //its false
$scope.hide = data.hideIt();
});
app.controller('SecCtrl', function($scope, data) {
$scope.hideAbove = function () {
var hide = true;
data.hideIt(hide);
console.log(data.hideIt(hide)) //now it is true
}
});
HTML:
<div ng-controller="MainCtrl">
<div ng-if="hide == false">
<p>Hello {{name}}!</p>
</div>
</div>
<div ng-controller="SecCtrl">
<div ng-click="hideAbove()">CLICK HERE </div>
</div>
Link to Plunkr:
http://plnkr.co/edit/zOAf5vGMTAd8A10NGiS1?p=preview
Is there no way to use a controller to hide code that is in another controller?
You dont need to use $emit, $rootScope.$broadcast or something else
in your code you asked to the factory the value of a local variable, you cant updates it because each time you start the method a new variable was created;
Here is a working example, hope it will help you
http://plnkr.co/edit/jBc3DJnzXNJUiVVwRAPw?p=preview
The factory declare some useful methods like updates and gets hide value
app.factory('HideFactory', function () {
var prototype = {};
var hide = false;
prototype.getDisplayMode = function() {
return hide;
}
prototype.hideIt = function (val) {
hide = typeof val == 'boolean' ? val : false;
return val;
};
return prototype;
});
The controllers declare some variables which are a reference to the factory methods
app.controller('MainCtrl', ['$scope', 'HideFactory',function($scope, HideFactory) {
$scope.name = 'World';
$scope.isHide = HideFactory.getDisplayMode;
}]);
app.controller('SecCtrl', ['$scope', 'HideFactory', function($scope, HideFactory) {
$scope.isHide = HideFactory.getDisplayMode;
$scope.hideAbove = function() {
HideFactory.hideIt(true);
}
}]);
And the html, the ng-if directive call the isHide method, linked to the getDisplayMode method of the factory
<body>
<div ng-controller="MainCtrl">
<div ng-if="!isHide()">
<p>Hello {{name}}!</p>
</div>
</div>
<div ng-controller="SecCtrl">
<div ng-click="hideAbove()">CLICK HERE </div>
</div>
</body>
You're about halfway there with your factory, you have most of a setter but not a getter. Here's what I'd change.
Factory:
app.factory('data', function () {
var fac = [];
var state = false;
fac.hideIt = function (hide) {
state = hide;
};
fac.hidden = function() {
return state;
}
return fac;
});
Controller:
app.controller('MainCtrl', function($scope, data) {
$scope.name = 'World';
$scope.hide = data.hidden;
});
HTML:
<div ng-controller="MainCtrl">
<div ng-hide="hide()">
<p>Hello {{name}}!</p>
</div>
</div>
Forked Plunker
please see here: http://plnkr.co/edit/3NEErc0zUpXlb1LarXar?p=preview
var app = angular.module('plunker', []);
app.factory('data', function() {
var fac = [];
var _hide = {};
hideIt = function(hide) {
console.log("from fact " + hide)
if (hide !== null) {
_hide.state = true;
return _hide;
} else
_hide.state = false;
return _hide;
};
return {
fac: fac,
hideIt: hideIt,
hide: _hide
};
});
app.controller('MainCtrl', function($scope, data) {
$scope.name = 'World';
//console.log(data.hideIt()); //its false
$scope.hide = data.hide;
});
app.controller('SecCtrl', function($scope, data) {
$scope.hideAbove = function() {
var hide = true;
data.hideIt(hide);
}
});
HTML:
<div ng-if="hide.state != true">
<p>Hello {{name}}!</p>
</div>
</div>
<div ng-controller="SecCtrl">
<div ng-click="hideAbove()">CLICK HERE</div>
</div>
</body>
You want to use $emit.
function firstCtrl($scope){
$scope.$on('someEvent', function(event, data) { console.log(data); });
}
function secondCtrl($scope){
$scope.$emit('someEvent', [1,2,3]);
}

Categories

Resources