AngularJS pre-fill input fields based on data from controller - javascript

I'm trying to pre-fill a form with a data from a controller.
Simple code looks like
<div ng-app="app" ng-controller="MainCtrl">
<input name="widget.title" ng-model="widget.title">
<input name="widget.content" ng-model="widget.content">
<button ng-click="set('foo')">set to foo</button>
</div>
and
angular.module('app', [])
.controller('MainCtrl', function($scope) {
$scope.widget = {title: 'abc'};
$scope.widget = {content: 'test'};
$scope.set = function(new_title) {
this.widget.title = new_title;
}
});
but it always pre-fill only last input field
JSFiddle: http://jsfiddle.net/b40nLuf2/

In your case, you overrides the first $scope.widget ($scope.widget = {title:'abc'}) with the second ($scope.widget = {content:'test'}).
You have to define one object $scope.widget with two attributes, title and content, in this way:
angular.module('app', [])
.controller('MainCtrl', function($scope) {
$scope.widget = {
title: 'abc',
content: 'test'
};
$scope.set = function(new_title) {
this.widget.title = new_title;
}
});

you can try this code snippets
angular.module('app', [])
.controller('MainCtrl', function($scope) {
$scope.widget = {title: 'abc',content: 'test'};
$scope.set = function(new_title) {
this.widget.title = new_title;
}
});
JSFIDDLE : click here to see

you need to create your object like this
$scope.widget = {
title: 'abc',
content: 'test'
};

Related

Want to refer to the variable in ng-repeat in another div ng-if. AngularJS

I have fetched docs from my database. now what I want to do is based on different doc.statuses, want to display different messages. How to go about it?
<p>
<a target="_blank" style="margin-right:5px" ng-repeat="doc in homeCtrl.getDocs(docType.objectId)" href="{{doc.document.url}}">
<div ng-if="doc.status == 'approved'">Hello</div>
<span class="label label-success"><i class="glyphicon glyphicon-hourglass"></i>{{doc.status}}</span>
<br>{{doc.comment}}<br>
</a>
</p>
so the ng-if in the div is not working. How to refer to the doc used in ng-repeat?
EDIT:
I still can't figure out. My controller looks like this(I'm using a Parse backend)
The controller looks like this
class HomeController {
constructor($scope, $state, itemsService, $location, $ionicLoading) {
'ngInject';
const self = this;
self.UserDocument = Parse.Object.extend('UserDocument');
self.$scope = $scope;
self.$scope.user = {};
self.$scope.objUserDocument = {};
self.$scope.userDocumentTypes = [];
self.loading = $ionicLoading;
// self.$scope.docs = [];
$scope.$on("$ionicView.beforeEnter", function(event, data) {
if (!Parse.User.current()) {
$location.url('/signup');
} else {
// self.$scope.user = window.buddy;
self._getDocumentTypes();
// self.$scope.user.firstName = objUser.get('firstName');
// self.$scope.user.lastName = objUser.get('lastName');
// console.log(objUser.get('docs'));
}
});
window.homeCtrl = this;
}
getDocs(id) {
const self = this;
if (self.$scope.user.docs && self.$scope.user.docs.length) {
var docs = self.$scope.user.docs.filter(d => id == d.docType.objectId);
return docs;
} else {
return [];
}
}
}
export default HomeController;
````
ng-if works fine:
HTML:
<div ng-repeat="item in items">
<span>{{item.id}}</span>
<span ng-if="item.status === 'approved'">approved</span>
<span ng-if="item.status === 'rejected'">rejected</span>
</div>
JS:
angular.module('myApp', [])
.controller('myCtrl', ['$scope', function($scope) {
$scope.items = [
{status: 'approved', id: 1},
{status: 'approved', id: 2},
{status: 'rejected', id: 3},
{status: 'rejected', id: 4}
]
}])
Here is the plnkr: http://plnkr.co/edit/wIX46rZHBNGHdv1S3LKg?p=preview
Try to move the function that retrieves the docs inside you controller and pass the result to ng-repeat instead.
ng-repeat="doc in docs"
and
.controller('YourController', function($scope) {
$scope.docs = getDocs(id);
});

Angular promises

I am running into an asynchronous issue with my stats controller. I have a controller that queries the db and returns the objects. In this controller I use the filter to get the ones with the platform Facebook and I put this into $rootScope.facebookObjects.
First controller:
app.controller('statsCtrl', function ($scope, $log, $http, $timeout, $filter, Data, $rootScope) {
Data.get('stats').then(function(data){
$scope.stats = data.data;
$scope.currentPage = 1; //current page
$scope.filteredItems = $scope.stats.length; //Initially for no filter
$scope.totalItems = $scope.stats.length;
$scope.list_pages = [
{
id: '5',
name: '5'
}, {
id: '10',
name: '10'
}, {
id: '20',
name: '20'
}, {
id: '50',
name: '50'
}, {
id: '100',
name: '100'
}
];
$scope.maxSize = 5;
$rootScope.facebookObjects = $filter('filter')($scope.stats, { platform: "facebook" });
$rootScope.twitterObjects = $filter('filter')($scope.stats, { platform: "twitter" });
});
$scope.setPage = function(pageNo) {
$scope.currentPage = pageNo;
};
$scope.filter = function() {
$timeout(function() {
$scope.filteredItems = $scope.filtered.length;
}, 10);
};
$scope.sort_by = function(predicate) {
$scope.predicate = predicate;
$scope.reverse = !$scope.reverse;
};
});
I have a second controller that uses the $rootScope.facebookObjects to populate the chart. The problem is I need to wait until the $rootScope.facebookObjects has a value. Currently my console log shows undefined. I am looking into promises but I am a little unsure which controller to use it in and how to properly use it.
Second Controller:
app.controller("PieCtrl", function ($scope, $rootScope, $timeout, $log) {
$log.log('facebook - '+$rootScope.facebookObjects.length);
});
$rootScope.$watch('facebookObjects', function(newValue, oldValue) {
//do your job
});
while you could use $watch to watch it, but i'm not sure it's a good way to share data between the controllers, and even more data is acync.
I have created an example for you with angular factory:
HTML:
<div ng-app="jsfiddle">
<div ng-controller="MainCtrl">
Data: {{data}}<br>
</div>
<div ng-controller="SecondCtrl">
Data: {{data}}<br>
</div>
</div>
Angular:
var app = angular.module('jsfiddle', []);
app.factory('myService', function($http) {
return {
async: function() {
return $http.get('https://api.myjson.com/bins/1v21f');
}
};
});
app.controller('MainCtrl', function( myService,$rootScope, $scope, $timeout) {
$scope.data = "oron";
myService.async().then(function(d) {
$timeout(function() {
$rootScope.data = d;
}, 1000);
});
});
app.controller('SecondCtrl', function($rootScope, $scope, $timeout) {
$scope.test = $rootScope.data;
});
MainCtrl is calling myService and store the response on the $rootScope.
then the when the value is ready it will update the data object on the SecondCtrl.
Thank you everyone for your help. Here is what I came up with based off of your answers.
First Controller:
$scope.facebookObjects = $filter('filter')($scope.stats, { platform: "facebook" });
$scope.twitterObjects = $filter('filter')($scope.stats, { platform: "twitter" });
$scope.$broadcast('update_chart_controller', {
fb: $scope.facebookObjects,
tw: $scope.twitterObjects
});
Second Controller:
$scope.$on("update_chart_controller", function(event, args) {
$scope.data = [args.fb.length, args.tw.length];
});

How to remove checkbox from array in angular js

Trying to create a function that will remove the selected checkbox items from the array but can't seem to figure it out. I have tried using splice and .pop() but it just won't remove the items I select. I think the best way would be to use an if statement but I do not know how to write it so that it shows true or false. Please help!!!
JS:
.controller('toDoCtrl', function($scope, toDoFactory){
//set $scope variables
$scope.tasks = toDoFactory.tasks;
$scope.removeTasks = toDoFactory.removeTasks;
})
.factory('toDoFactory', ['$http', function($http){
var toDo = {
tasks: [],
removeTasks: function(selectedTask){
angular.forEach(toDo.tasks, function(value, selectedTask){
var i = toDo.tasks.indexOf(value);
toDo.tasks.splice(toDo.tasks.indexOf(i), 1);
});
}
};
return toDo;
}])
HTML:
<button ng-click="removeTasks()">Remove</button>
I did not really understood if you wanted to delete all selected tasks or just one.
Anyway, you can do this for example :
JS:
app
.controller('toDoCtrl', function($scope, toDoFactory){
//set $scope variables
$scope.data = {};
$scope.data = toDoFactory.data;
$scope.removeTasks = toDoFactory.removeTasks;
$scope.removeTask = toDoFactory.removeTask;
})
.factory('toDoFactory', ['$http', function($http){
var toDo = {
data : {
tasks: [
{text: "hello world", done: false},
{text: "hello world2", done: false},
{text: "hello world3", done: false}
]
},
removeTasks: function(){
toDo.data.tasks = toDo.data.tasks.filter(function(task){
return !task.done;
});
},
removeTask: function(index){
toDo.data.tasks.splice(index, 1);
},
};
return toDo;
}]);
HTML:
<body ng-controller="toDoCtrl">
<div ng-repeat='task in data.tasks'>
<input type='checkbox' ng-model='task.done' />
<span>{{task.text}}</span>
</div>
<br/>
<button ng-click="removeTasks()">Remove</button>
</body>
Plunkr :
https://plnkr.co/edit/bTG0fEUZl1uoTIFT1NhC?p=preview

Call function or pass data to another controller AngularJS

I already have seem other topics with this kind of issue, but no one could help me... So here is my issue:
I have a navbar with a button for search, this buttons makes and get request from a webservice and returns a json object which must be apply to fill an table list. The problem is, my button and my table are in separated controllers, and it does work like I expected.
var app = angular.module('clientRest', []).controller('lista', ['$scope', 'loadLista', function($scope, loadLista) {
$scope.contatos = loadLista.getContatos();
}]).controller('pesquisa', ['$scope', '$http', 'loadLista', function($scope, $http, loadLista) {
$scope.listar = function() {
$http.get("http://localhost/wsRest/index.php/contato").success(function(response) {
loadLista.setContatos(response);
});
};
}]).service('loadLista', function() {
var contatos = [];
return {
getContatos: function() {
return contatos;
},
setContatos: function(c) {
contatos = c;
}
};
});
My code...
When I call listar() from pesquisa controller I need to send received data to $scope.contatos from lista controller to make my ng-repeat work, everything with a single click.
How can I do it?
Thanks everyone
Better to use a service to share data between two controllers / modules as this might be the best approach. You can refer the code segment given below to understand the concept.
angular.module('app.A', [])
.service('ServiceA', function() {
this.getValue = function() {
return this.myValue;
};
this.setValue = function(newValue) {
this.myValue = newValue;
}
});
angular.module('app.B', ['app.A'])
.service('ServiceB', function(ServiceA) {
this.getValue = function() {
return ServiceA.getValue();
};
this.setValue = function() {
ServiceA.setValue('New value');
}
});
In order to trigger the data receipt event, you may use
Broadcast / emit messages - with #broadcast / #emit
An angular promise with a call back
Controller initiation function to reload the previously read information from a service
.controller('MyController', function($scope, ServiceA) {
$scope.init = function() {
$scope.myValue = ServiceA.getValue();
};
// Call the function to initialize during Controller instantiation
$scope.init();
});
Use $rootScope.$emit to emit a change event when setting the variable and use $on to get the value in the lista controller. I used customListAr here just to demostrate a button click. Does this help?
var app = angular.module('clientRest', [])
.controller('lista', ['$scope', 'loadLista', '$rootScope',
function($scope, loadLista, $rootScope) {
console.log(loadLista);
$scope.contatos = loadLista.getContatos();
$rootScope.$on('change', function() {
$scope.contatos = loadLista.getContatos();
});
}
])
.controller('pesquisa', ['$scope', '$http', 'loadLista',
function($scope, $http, loadLista) {
$scope.listar = function() {
$http.get("http://localhost/wsRest/index.php/contato").success(function(response) {
loadLista.setContatos(response);
});
};
$scope.customListAr = function() {
loadLista.setContatos(["item 1" , "item 2", "item 3"]);
}
}
])
.service('loadLista', ['$rootScope',
function($rootScope) {
var contatos = [];
return {
getContatos: function() {
return contatos;
},
setContatos: function(c) {
contatos = c;
$rootScope.$emit('change');
}
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="clientRest">
<div ng-controller="lista">
<ul>
<li ng-repeat="a in contatos">{{a}}</li>
</ul>
</div>
<div ng-controller="pesquisa">
<button ng-click="customListAr()">Click Me</button>
</div>
</div>
Your problem is that when you do $scope.contatos = loadLista.getContatos(); you are setting a static value, and angular is unable to effectively create a watcher for that object because your setContatos method is creating a new object each time. To get around this, have the controller's scope hold a reference to the parent object and then it will automatically have a watcher on that object.
var app = angular.module('clientRest', [])
.controller('lista', ['$scope', 'loadLista', function($scope, loadLista) {
$scope.contatos = loadLista.contatos;
}])
.controller('pesquisa', ['$scope', '$http', 'loadLista', function($scope, $http, loadLista) {
$scope.listar = function() {
$http.get("http://localhost/wsRest/index.php/contato"
).success(function (response) {
loadLista.contatos.data = response;
});
};
}])
.service('loadLista', function() {
var lista = {
contatos: {},
};
return lista;
});
// view:
<ul>
<li ng-repeat="contato in contatos.data">
{{ contato }}
</li>
</ul>

Dynamic controllers bound from scope

I would like to create "components" dynamically, based on data received from my backend. The goal is to display parts of my application, without using server side templating : instead of displaying components server-side, the server sends JSON data containing which components should be displayed.
Here is what I've got so far :
var module = angular.module('testApp', []);
module.controller('Ctrl1', ['$scope', function ($scope) {
$scope.test = "test 1";
}])
.controller('Ctrl2', ['$scope', function ($scope) {
$scope.test = "test 2";
}])
.controller('ComponentsController', ['$scope', function ($scope) {
// this is JSON returned by backend
$scope.components = [{
name: "Wd1",
controller: "Ctrl1",
}, {
name: "Wd2",
controller: "Ctrl2",
}];
$scope.test = "test";
}]);
And my view :
<div ng-app="testApp">
<div ng-controller="ComponentsController">
<div ng-repeat="component in components">
<p>{{component.name}} - {{component.controller}}</p>
</div>
<div ng-repeat="component in components">
<p ng-controller="component.controller">{{test}}</p>
</div>
</div>
</div>
However, I get the following error :
Error: Argument 'component.controller' is not a function, got string
I tried to write a directive, assigning controller names during compile, but as it is done during compile, it doesn't work with binding...
Here is a fiddle : http://jsfiddle.net/mathieu/bTQA5/
Just do it controllers name, not string:
function ComponentsController($scope) {
$scope.components = [{
name: "Wd1",
controller: Ctrl1,
}, {
name: "Wd2",
controller: Ctrl2,
}];
$scope.test = "test";
}
Bind the functions to the data in scope:
function ComponentsController($scope) {
$scope.Ctrl1 = function () {
$scope.test = "test 1";
}
$scope.Ctrl2 = function () {
$scope.test = "test 2";
}
$scope.components = [{
name: "Wd1",
controller: $scope.Ctrl1
}, {
name: "Wd2",
controller: $scope.Ctrl2
}];
$scope.test = "test";
}
And here's the updated jsFiddle.
Note that there's still a logical issue here; The {{ test }} binding will be evaluated as soon as the controller does, so the resulted text (on every binding) will be the last evaluation made, i.e. "Test 2", in our case.
You may want to tie logic to handlers instead, e.g. ng-click, to be executed on demand:
<div ng-repeat="component in components">
<button ng-controller="component.controller"
ng-click="component.controller()">
Call {{ component.name }} controller
</button>
</div>
And here it is demonstrated live as well.
This answer is based on the first version of this question, which included the following code:
function ComponentsController($scope) {
$scope.components = [{
name: "Wd1",
controller: "Ctrl1",
}, {
name: "Wd2",
controller: "Ctrl2",
}];
$scope.test = "test";
}
function Ctrl1($scope) {
$scope.test = "test 1";
}
function Ctrl2($scope) {
$scope.test = "test 2";
}
You can use the following directive which will insert a controller based on a name:
var module = angular.module('testApp', []);
module
.directive('dynamicController', ['$controller', function($controller) {
return {
restrict: 'A',
scope: true,
link: function (scope, element, attrs) {
var locals = {
$scope: scope,
$element: element,
$attrs: attrs
};
element.data('$Controller', $controller(scope.$eval(attrs.dynamicController), locals));
}
};
}
])
var module = angular.module('testApp', []);
module
.directive('dynamicController', ['$controller',
function($controller) {
return {
restrict: 'A',
scope: true,
link: function(scope, element, attrs) {
var locals = {
$scope: scope,
$element: element,
$attrs: attrs
};
element.data('$Controller', $controller(scope.$eval(attrs.dynamicController), locals));
}
};
}
])
.controller('Ctrl1', ['$scope',
function($scope) {
$scope.test = "test 1";
}
])
.controller('Ctrl2', ['$scope',
function($scope) {
$scope.test = "test 2";
}
])
.controller('ComponentsController', ['$scope',
function($scope) {
$scope.components = [{
name: "Wd1",
controller: "Ctrl1",
}, {
name: "Wd2",
controller: "Ctrl2",
}];
$scope.test = "test";
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.min.js"></script>
<div ng-app="testApp">
<div ng-controller="ComponentsController">
<div ng-repeat="component in components" dynamic-controller="component.controller">
<p><span>{{test}}</span>
</p>
</div>
</div>
</div>

Categories

Resources