AngularJS edit scope with same name from another method - javascript

I would like to update some value in scope with same name in another method of same class.
Problem is that update method is not working if i'm trying to update scope named gridData.
Should i use scope apply or something Simillar in Angular?
Here is my code:
orders.controller('OrdersCtrl', function ($scope, $http, $rootScope, $location, $notification, $routeParams, ApiService) {
$scope.gridData = {};
$scope.initGrid = function () {
$scope.gridData = new kendo.data.ObservableArray([
{ artist: "Pink Floyd", track: "The dark side of the Moon" },
{ artist: "The Beatles", track: "I've just seen a face" },
{ artist: "Queen", track: "Innuendo" }
]);
$scope.test = function() {
console.log('dede');
};
$scope.data.test,$scope.gridColumns = [
{ field: "artist", title: "Artist" },
{ field: "track", title: "Track" }
];
};
$scope.update = function() {
// empty JSON object
console.log($scope.gridData);
// Here i get error
$scope.gridData[0].set("track", "Hey you");
};
Thanks for any example how to do it correctly.

Related

how to add dynamic field to ui-grid header-name field

Grid which has one field name Users and requirement is it should display Users(count of Users) in ui-grid header-name. How can I get that.
This is my JS file code:
var userCount= response.usercount;
columnDefs: [{
name: 'Users', // Along with Users i want count also
width: '25%',
cellTemplate: 'beacon-template'
},
How can I get that?
You can always change the header text. Sounds like you can put a watch to the count value and do something similar like the following:
$scope.$watch('yourCountValue', function(newVal){
$scope.gridOptions.columnDefs[0].displayName = 'Users(' + newVal + ')';
$scope.gridApi.core.notifyDataChange(uiGridConstants.dataChange.COLUMN);
})
the code may vary in your case. For example, you may watch the $scope.data change instead and use $scope.data.length to concat the displayName. You may have select header and index will be 1 instead of 0, etc.
Updated Answer: did you forget to inject ui.grid and uiGridConstants?
var app = angular.module('myApp', ['ui.grid']);
app.controller('appCtrl', ['$scope', 'uiGridConstants', function($scope, uiGridConstants) {
$scope.gridOptions = {
columnDefs: [
{field: 'field1', displayName: 'User 1'},
{field: 'field2', displayName: 'User 2'},
],
data: [
{ field1: "user 1", field2: "bar"},
{ field1: "user 2", field2: "bar"},
{ field1: "user 3", field2: "bar"}
],
onRegisterApi: function(gridApi) {
$scope.gridApi = gridApi;
}
};
//put the watch here
/...
}]);

Dynamically update and check an array of Objects

So I have a callback function that returns a data object from the dom (there is a list of items and every time you select an item it returns it as an object). Here is the call back function:
$scope.fClick = function( data ) {
$scope.x = data;
}
The object returned from fClick looks like this when you select an item from the dropdown : { name: "English", ticked: true }
When you deselect it from the dropdown it would return something like this:
{ name: "English", ticked: false }
Now I keep an array something like $scope.output to maintain a list of the returned objects. However, what I want to do is add an object returned from scope.fClick to $scope.output only if there isn't an object in output already with the same property "name" value. So right now in my implementation both { name: "English", ticked: false } and { name: "English", ticked: true } get added to the array. Instead I want it to update the ticked property. So, for instance if if $scope.output = { name: "English", ticked: false } and then scope.fClick returns { name: "English", ticked: true}. When I push this value to $scope.output I want it to the update the existing object's tick property so $scope.output = { name: "English", ticked: false } becomes $scope.output = { name: "English", ticked: true }
This is what I have tried:
$scope.fClick = function( data ) {
$scope.x = data;
}
$scope.$watch(function () {
return $scope.y = $scope.x;
},function (newValue, oldValue) {
var id = $scope.output.indexOf(newValue);
if(id === -1){
$scope.output.push(newValue);
}
else {
$scope.output[id].tick = newValue.tick;
}
console.log($scope.output);
},true);
How do I make this work?
Set & Get selected values, name and text of Angularjs isteven-multi-select
<div isteven-multi-select
input-model="marks"
output-model="filters.marks"
button-label="name"
item-label="name"
tick-property="ticked"
selection-mode="multiple"
helper-elements="all none filter"
on-item-click="fClick( data )"
default-label="Select marks"
max-labels="1"
max-height="250px">
</div>
Add items
$scope.marks= [
{ name: 'Mark I', value: 'Mark i', text: 'This is Mark 1', ticked: true },
{ name: 'Mark II', value: 'Mark ii', text: 'This is Mark 2' },
{ name: 'Mark III', value: 'Mark iii', text: 'This is Mark 3' }
];
Get selected item (on change)
$scope.fClick = function (data) {
console.log(data.name);
console.log(data.value);
console.log(data.text);
return;
}
Select item (Dynamically)
$scope.abc = function (data) {
console.log(data.element1, data.element2);
angular.forEach($scope.marks, function (item) {
if (item.value == data.element1) {
item.ticked = true;
}
else {
item.ticked = false;
}
});
}
Deselect item
$scope.marks.map(function (item) {
if (item.value == "")
item.ticked = true;
else
item.ticked = false
});
You can do the following by "simulate" a key/value map.
Controller
(function(){
function Controller($scope) {
$scope.data = [
{name: 'English', ticked: true},
{name: 'French', ticked: false}
];
//Represent a map key - value
$scope.output = {};
$scope.update = function(index){
//Change the ticked value by opposite
$scope.data[index].ticked = !$scope.data[index].ticked;
//Set the value to our map
$scope.output[index] = $scope.data[index].ticked;
}
}
angular
.module('app', [])
.controller('ctrl', Controller);
})();
Here, when you will update $scope.output, if the key exist, it will erase it by the new value, instead of it will create a new key/value pair.
HTML
<body ng-app="app" ng-controller="ctrl">
<ul>
<li ng-repeat="item in data">{{item.name}} {{item.ticked}} <button type="button" ng-click="update($index)">update</button></li>
</ul>
</body>

Angularjs: call a controller method with param from a directive dropdown on change event

I have made a dropdown directive. On selecting a value from the dropdown, a method from the controller is called with the selected filter passed. Everything works fine except that the method is always returning the default selected value, no matter, what is selected.
html:
<div ng-controller="Ctrl">
<div>
<dropdown filters="filters" filter="filter" select="selectFilter(filter)"></dropdown>
</div>
</div>
javascript:
var app = angular.module('app', []);
function Ctrl($scope){
$scope.filters = [
{ Id: 1, Name: "All" }, { Id: 2, Name: "filter1" }, { Id: 3, Name: "filter2" }, { Id: 4, Name: "filter3"}
];
$scope.filter = $scope.filters[0];
$scope.selectFilter = function(selectedFilter){
alert(selectedFilter.Name);
};
}
app.directive('dropdown', function(){
return {
restrict: "E",
scope: {
filter: "=",
filters: "=",
select: "&"
},
template: "<select ng-model=\"filter\" ng-change=\"select(filter)\" ng-options=\"f.Name for f in filters\"></select>"
};
});
Working fiddle: http://jsfiddle.net/wXV6Z/98/
You're using wrong syntax to call method binding.
Try:
ng-change=\"select({filter:filter})\
DEMO
I made this, but the other answer seems better :P
http://jsfiddle.net/wXV6Z/101/
var app = angular.module('app', []);
function Ctrl($scope, $element){
$scope.filters = [
{ Id: 1, Name: "All" }, { Id: 2, Name: "filter1" }, { Id: 3, Name: "filter2" }, { Id: 4, Name: "filter3"}
];
$scope.filter = $scope.filters[0];
}
app.directive('dropdown', function(){
return {
restrict: "E",
scope: {
filter: "=",
filters: "=",
},
template: "<select ng-model=\"filter\" ng-change=\"selectFilter(filter)\" ng-options=\"f.Name for f in filters\"></select>",
controller: function($scope, $element) {
$scope.selectFilter = function(selectedFilter) {
alert(selectedFilter.Name);
}
}
}
});

AngularJS : cannot connect factory to controller

I'm sorry if this is an easy question. I'm new and probably don't understand the right things to search for to find the answer.
I've basically followed this angularJS tutorial http://www.youtube.com/watch?v=i9MHigUZKEM
I've gotten through all of it except setting up a factory that connects to my controller.
Here is the code for the factory:
demoApp.factory('simpleFactory', function(){
var people = [
{ name: 'Will', age: '30' },
{ name:'Jack', age:'26' },
{ name: 'Nadine', age: '21' },
{ name:'Zach', age:'28' }
];
var factory = {};
factory.getPeople = function() {
return people;
};
});
Here is the controller:
demoApp.controller('FirstCtrl', ['$scope', 'simpleFactory', function ($scope, simpleFactory) {
$scope.people = simpleFactory.getPeople();
}]);
And just a simple repeat in the HTML:
Name:
<input type="text" ng-model="filter.name"> {{ nameText }}
<ul>
<li ng-repeat="person in people | filter:filter.name | orderBy: 'name'">{{ person.name }}- {{ person.age }}</li>
</ul>
The error I get is "TypeError: Cannot call method 'getPeople' of undefined" in the javascript console.
Note: This all works correctly when within the controller I have the data object hardcoded in like so:
demoApp.controller('FirstCtrl', ['$scope', 'simpleFactory', function ($scope, simpleFactory) {
$scope.people = [
{ name: 'Will', age: '30' },
{ name:'Jack', age:'26' },
{ name: 'Nadine', age: '21' },
{ name:'Zach', age:'28' }
];
}]);
A small change in your service;
demoApp.factory('simpleFactory', function(){
var people = [
{ name: 'Will', age: '30' },
{ name:'Jack', age:'26' },
{ name: 'Nadine', age: '21' },
{ name:'Zach', age:'28' }
];
return {
getPeople: function() {
return people;
};
}
});
And in your controller
demoApp.controller('FirstCtrl', ['$scope', 'simpleFactory', function ($scope, simpleFactory) {
$scope.people = simpleFactory.getPeople();
}]);
Essentially you're just missing the return statement from your 'factory' object, but it might be clearer if you do a little renaming as well to avoid confusion.
Example, adapted from the AngularJS book:
demoApp.factory('People', function(){ // Renamed factory to be more descriptive
var people = {}; // Renamed 'factory' to 'people', as an object we can prototype more functions later
people.query = function() { // called query, but could be getPeople
return [ // just return a static array for now
{ name: 'Will', age: '30' },
{ name:'Jack', age:'26' },
{ name: 'Nadine', age: '21' },
{ name:'Zach', age:'28' }
];
}
return people;
});
So now your controller can pull this information in:
demoApp.controller('FirstCtrl', ['$scope', 'People', function ($scope, People) { // dependency injection
$scope.people = People.query();
});
So now we have a descriptive factory for People that returns an object, one of which is called query. We can later update this query function to read in parameters, fire off AJAX calls and do some complicated stuff. But one step at a time :)

Looping through deep objects in ng-repeat

I'm in angular and i have a object like this.
var items = [{
title: 'Something',
children: [
{ title: 'Hello World' },
{ title: 'Hello Overflow' },
{ title: 'John Doe', children: [
{ title: 'Amazing title' },
{ title: 'Google it' },
{ title: 'I'm a child', children: [
{ title: 'Another ' },
{ title: 'He\'s my brother' },
{ title: 'She\'s my mother.', children: [
{title: 'You never know if I'm going to have children'}
]}
]}
]}
]
}];
I wan't to loop through all of these so i have something like this.
    • Something
       • Hello World
       • Hello Overflow
       • John Doe
          • Amazing Title
          • Google it
          • I'm a child
              • Another
              • He's my brother
              • She's my mother
                  • You never know if I'm going to have children
The problem is I wouldn't know how deep this object will go or what's in it. so I wouldn't be able to do it manually. I have done a basic loop with ng-repeat in the fiddle provided at the bottom, but i can't figure out how I can automatically loop through these and create nested <ul>'s and <li>'s.
What would be the best way to accomplish this?
Demo: http://jsfiddle.net/XtgLM/
You don't need to make a custom directive, what you want is to use an inline template that calls it's self.
I forked your fiddle.
http://jsfiddle.net/MasterMorality/E99Gh/2/
basically it looks like this:
<script type='text/ng-template' id="item.html">
...
<div ng-repeat="x in x.childrens" ng-include="'item.html'"></div>
</script>
...
<div ng-repeat="x in things" ng-include="'item.html'"></div>
I should note that you are not actually overwriting x, since angular creates a new scope for each repeated item.
Here you go:
html
<div ng-app="app" ng-controller="test">
<ul>
<li nested-item ng-repeat="item in items">{{item.title}}</li>
</ul>
</div>
JavaScript
var items = [{
title: 'Something',
children: [
{ title: 'Hello World' },
{ title: 'Hello Overflow' },
{ title: 'John Doe', children: [
{ title: 'Amazing title' },
{ title: 'Google it' },
{ title: 'Im a child', children: [
{ title: 'Another ' },
{ title: 'He\'s my brother' },
{ title: 'She\'s my mother.', children: [
{title: 'You never know if im going to have children'}
]}
]}
]}
]
}];
var app = angular.module('app', []);
app.controller('test', function( $scope ) {
$scope.items = items;
});
app.directive('nestedItem', ['$compile', function($compile){
return {
restrict: 'A',
link: function(scope, element){
console.log(element);
if (scope.item.children){
var html = $compile('<ul><li nested-item ng-repeat="item in item.children">{{item.title}}</li></ul>')(scope);
element.append(html);
}
}
};
}]);
I forked your fiddle:
http://jsfiddle.net/c4Kp8/
Actually I must confess that I like Master Morality's approach but you can also go with a custom directive. The key thing to know if you go that route is that you need to intercept on the item level to manually check if the current item has children, and if so, $compile the directive for the node yourself.
UPDATE
However, there is one thing that should bother us in the above code. The duplication of html code (inlined in the directive) is a code smell. If you like, you can get really funky and fix this by introducing a generic template-code directive which doesn't do anything else but providing the code of the node where it is applied on as a template for other directives.
So then our solution would look like this:
html
<div ng-app="app" ng-controller="test">
<ul template-code>
<li nested-item ng-repeat="item in items">{{item.title}}</li>
</ul>
</div>
JavaScript
var items = [{
title: 'Something',
children: [
{ title: 'Hello World' },
{ title: 'Hello Overflow' },
{ title: 'John Doe', children: [
{ title: 'Amazing title' },
{ title: 'Google it' },
{ title: 'Im a child', children: [
{ title: 'Another ' },
{ title: 'He\'s my brother' },
{ title: 'She\'s my mother.', children: [
{title: 'You never know if im going to have children'}
]}
]}
]}
]
}];
var app = angular.module('app', []);
app.controller('test', function( $scope ) {
$scope.items = items;
});
app.directive('templateCode', function(){
return {
restrict: 'A',
controller: function(){},
compile: function(element){
element.removeAttr('template-code');
//ATTENTION: We need to trim() here. Otherwise AngularJS raises an exception
//later when we want to use the templateCode in a $compile function.
//Be aware that we assume a modern browser
//that already ships with a trim function.
//It's easy to secure that with a polyfill.
var templateCode = element.parent().html().trim();
return function(scope, iElement, iAttrs, controller){
controller.templateCode = templateCode;
}
}
}
});
app.directive('nestedItem', ['$compile', function($compile){
return {
restrict: 'A',
require: '^templateCode',
link: function(scope, element, iAttr, controller){
if (scope.item.children){
scope.items = scope.item.children;
var html = $compile(controller.templateCode)(scope);
element.append(html);
}
}
};
}]);
Plunker: http://jsfiddle.net/2rQWf/
You're probably going to need to create your own directive passing in the object to iterate over. Put a watch on the object passed in and when that fires run some recursive function that appends elements to the element that the directive is on.
You can get at the DOM element from the element parameter on the directive link function. You can obviously append DOM elements using that same element parameter.

Categories

Resources