I'm trying to use angularJs (version 1.3.0) with kendo-asp.net.mvc (version 2015.1.429).
I want to know if is possible enable/disable Kendo Razor helper DropDownList using AngularJs.
Code Example (i want disabled kendo dropdownlist "DdlTest" if i choose the first element "Black" with value "1" from dropdownlist "color") :
.cshtml Page
<div ng-app="myApp">
<div ng-controller="MainController">
<h4>Cap Color</h4>
#(Html.Kendo().DropDownList()
.Name("color")
.HtmlAttributes(new
{
ng_model="selectedField",
ng_change="changeField(kendoEvent)"
})
.DataTextField("Text")
.DataValueField("Value")
.BindTo(new List<SelectListItem>() {
new SelectListItem() {
Text = "Black",
Value = "1"
},
new SelectListItem() {
Text = "Orange",
Value = "2"
}
})
)
<h4 style="margin-top: 2em;">Cap Size</h4>
#(Html.Kendo().DropDownList()
.Name("DdlTest")
.BindTo(new List<string>() {
"S - 6 3/4\"",
"M - 7 1/4\"",
"L - 7 1/8\"",
"XL - 7 5/8\""
})
)
</div>
</div>
This is AngularJs Code
<script>
var app = angular.module("myApp", ["kendo.directives"]);
app.controller("MainController", function($scope) {
$scope.selectedField = "0";
$scope.changeField = function(e) {
switch ($scope.selectedField) {
case '1':
$scope.DdlTest.enable(false);
break;
default:
$scope.DdlTest.enable(true);
break;
}
}
});
</script>
When i change the value of dropdownlist i receive:
Error: $scope.DdlTest is undefined
I tried to insert in the HtmlAttributes of dropdownlist "DdlTest" the value:
kendo_drop_down_list = "DdlTest"
but it doesn't work on IE and Firefox, it seems work only on chrome.
QUESTION
Is it possible use angularJs with kendo mvc components in Razor?
If is possible, how i can enable/disable a kendo dropdownlist?
Related
I have a weird behavior of FormGroup.
What I am doing exactly is that I am generating FormControls into the desired form group, according to number of key properties of an array.
Lets say I have the following array:
arrayData = [
{_id: 123, _name: 'XYZ', gender: 'Male'},
{_id: 124, _name: 'XYW', gender: 'Female'}
];
The extracted arra properties are as the following:
this.odkDataIndexes = ['_id', 'name', 'gender'];
Now, for each index, I need to generate a form control into the indexesForm form group:
async createIndexesForm(extractedIndexesArray) {
const controls = extractedIndexesArray.reduce((g, k) => {
g[k] = '';
return g;
}, {});
this.indexesForm = this.fb.group({controls});
console.log(this.indexesForm);
}
This function will be fired, once the user click on a button having a click event: (click)=generateMappingFields():
async generateMappingFields() {
this.showFields = false;
this.removeUnnecessaryFieldsMsg = '';
if (this.odkDataIndexes.length > 0) {
await this.createIndexesForm(this.odkDataIndexes).then(() => {
this.showFields = true;
this.tabIndex = 1;
});
}
}
For the console.log(this.indexesForm); output, the for appears to be created:
And it contains the following controls:
Which are exactly the same indexes, that I've extracted from my data.
Now I need to display these controls as following:
<div class="flexColEven">
<mat-spinner *ngIf="!indexesForm" value="50" class="setSpinnerOnTop" diameter="75" [color]="medair-color">
</mat-spinner>
<div *ngIf="showFields && indexesForm">
<div [formGroup]="indexesForm" *ngIf="indexesForm" class="flexRow">
<!-- {{indexesForm.valid | json}} -->
<div *ngFor="let controlName of odkDataIndexes">
<span></span>
<div>
<h3>ONA field: {{controlName}}</h3>
</div>
<mat-form-field class="formFieldWidth" color="warn" appearance="fill">
<mat-label>{{controlName}}</mat-label>
<mat-select [formControlName]="controlName">
<mat-option *ngFor="let de of dataElementsDetails; let i = index;"
[value]="de.id">
{{de.displayName}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</div>
</div>
When indexesForm is created, I will show the div having a drop down list for each controller, which is showing properly, but showing at the same time an error, for each controller saying:
core.js:6185 ERROR Error: Cannot find control with name: '_id'
core.js:6185 ERROR Error: Cannot find control with name: '_tag'
...
But the fields are shown properly as this stackblitz shows you.
And when I need to get the value of each drop down list:
mapping() {
this.odkDataIndexes.forEach((arrayIndexControl) => {
console.log(arrayIndexControl);
console.log(this.indexesForm.get(arrayIndexControl));
});
}
I can clearly see the arrayIndexControl which is the name of the form control of the indexesForm group, but the second console is displaying the following response:
null
And if I consoled (this.indexesForm.get(arrayIndexControl).value);, it will return an error of undefined.
Here is a stackblitz having an example of data I have.
On this line this.indexesForm = this.fb.group({controls}); you are creating a form group with a single form control in it called controls. Replace with this: this.indexesForm = this.fb.group(controls);
In general, doing const obj = {controls}; is the same as const obj = { controls: controls };
I have a kendo ui dropdownlist with angularjs in my html:
<select kendo-drop-down-list="dropdownlistCatalogs" k-options="optionsDropDownListCatalogs" data-role="dropdownlist" style="display: none;">
<option value="2" selected="selected">Test1</option>
<option value="3">Test2</option>
<option value="4">Test3</option>
</select>
In the angularjs controller, everytime i click on an item in the dropdownlist, i call this function to remove the selected item from the dropdown control:
function removeItemFromDropDown(e) {
var index = e.item.index();
var selectedItem = $scope.dropdownlistCatalogs.dataItem(e.item.index());
$scope.optionsDropDownListCatalogs.dataSource.remove(selectedItem);
}
Now, i want set the selected option to non existing item to show an empty value.
I have tried with:
$scope.dropdownlistCatalogs.value(-1);
but not working
How can i set the dropdownlist by value()?
I'm not sure much about angularjs and if things are different. I see $scope in there which I guess is of angular, since i dont see it defined anywhere. But Usually value will help you with this if using jquery
Add a default blank value at the top with id:-1 and set the default value as 1.
On click of a button, you can change the value to -1
It would look like this :
var data = [
{ "text": "" , id: -1 },
{ "text": "aaa",id: 1 },
{ "text": "bbb",id: 2 },
{ "text": "ccc", id:3}
];
$("#ddl").kendoDropDownList({
dataTextField: "text",
dataValueField: "id",
dataSource: data,
index: 3
});
$("#button").on("click", function () {
var dropdownlist = $("#ddl").data("kendoDropDownList");
dropdownlist.value(-1);
});
Here is an working example
What I'm trying to do is have a service (lets say: myService) that holds specific data like objects representing printers present and selected:
var localPrinters = [{ id: 12, name: 'HP', type: 'laser' },
{ id: 33, name: 'Lexmark', type: 'laser' }];
var activePrinter = {};
In some view that gets shown occasionally (like app settings), I have a controller that would define variables in the local scope which would point to the objects in the injected myService.
The view would then use ng-repeat to iterate over printer objects in localPrinters and display radio buttons that correspond to each object in the array..
Now i need two things..
1) update the activePrinter upon radiobutton selection change with the corresponding object value
2) in case the activePrinter already contains an object, when the view loads i want the corresponding radio to be checked already (if its value object matches the object in activePrinter, otherwise none should be selected.
I've managed 1) in a couple of ways.. either sticking to the model usage or adding methods to call upon ng-change.
//pseudocode
<container ng-repeat="printer in printers" >
<radio ng-value="printer" ng-model="$scope.activePrinter"/>
</container>
or
//pseudocode
<container ng-repeat="printer in printers" >
<radio ng-value="printer" ng-change="selectPrinter(printer)" "ng-model="$scope.activePrinter"/>
</container>
What i'm having trouble with is 2)
Not sure if there's a way in angular to automatically figure out some of the printer values matches the activePrinter selection and make the radio checked. Also not sure of the way i'm using ng-model for this purpose.
Any pointers?
Thanks!
You can do that in this way:
var app = angular.module('app', []);
app.controller('firstCtrl', function($scope) {
$scope.printers = [{
id: 12,
name: 'HP',
type: 'laser'
}, {
id: 33,
name: 'Lexmark',
type: 'laser'
}];
$scope.activePrinter = {};
//set default printer
$scope.activePrinter.printer = $scope.printers[0]
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="app">
<div ng-controller="firstCtrl">
<div class="container" ng-repeat="printer in printers">
<label>{{printer.name}}</label>
<input type="radio" ng-value="printer" ng-model="activePrinter.printer" />
</div>
Active Printer:{{activePrinter.printer.id}} | {{activePrinter.printer.name}} | {{activePrinter.printer.type}}
</div>
</body>
I have an order line grid where I need to be able to open the popup editor form programmatically with the edit form fields pre-populated (using AngularJs).
In the HTML, I have a lineGrid and an addButton, which calls addRow() on the ticketEntryController:
<div id="wrapper" class="container-fluid" ng-controller="ticketEntryController">
<div ng-controller="ticketLineController">
<div kendo-grid="ticketLineGrid" k-options="getTicketLineGridOptions()"></div>
</div>
<button id="addButton" ng-click="addRow()" class="btn btn-primary btn-sm">Add Row</button>
</div>
Here is the ticketEntryController:
(function () {
'use strict';
angular.module('app').controller('ticketEntryController', ticketEntryController);
function ticketEntryController($scope) {
$scope.lineGrid = {};
$scope.addRow = function () {
var item = { itemNo: 'TEST123', itemDescr: 'Some description' };
$scope.$broadcast('AddRow', item);
}
}
})();
Here is part of the ticketLineController:
function ticketLineController($scope) {
$scope.$on('AddRow', function(event, item) {
console.log("ticketLineController, AddRow: " + item.itemNo);
$scope.itemNo = item.itemNo;
$scope.itemDescr = item.itemDescr;
$scope.ticketLineGrid.addRow();
});
Plunker: http://plnkr.co/edit/VG39UlTpyjeTThpTi4Gf?p=preview
When the Add Row button is clicked, the editor popup form opens up, but all fields are empty. How can I populate the fields (like they are when you click the Edit button for an existing row)?
I figured out how to get a row to be pre-populated for you, although I'm not sure if this is necessarily the best way to do it, but it does accomplish the job - I'm more familiar with AngularJs, not so much with Kendo UI.
The only place that the Kendo API allows you to change/set the new item that you are adding is in the edit event but I couldn't see a way to send your own object along to the event when you call addRow so you need to have a reference to a shared object in your controller with I called itemForAdd. Before calling addRow() in your controller, you need to set the itemForAdd object with the actual object that you want to pre-populate the form with.
var itemForAdd = {};
$scope.$on('AddRow', function(event, item) {
// save reference to item to use for pre-population
itemForAdd = item;
$scope.ticketLineGrid.addRow();
});
Now in the edit event that the Kendo API sends out, you can populate the items from your selected item in the model item. It's not really required, but I also like to clear out objects that I use like this so in the save and cancel events, I clear out the shared itemForAdd object.
edit: function (e) {
if (e.model.isNew()) {
e.model.set("itemNo", itemForAdd.itemNo);
e.model.set("itemDescr", itemForAdd.itemDescr);
}
var popupWindow = e.container.getKendoWindow();
e.container.find(".k-edit-form-container").width("auto");
popupWindow.setOptions({
width: 640
});
},
save: function(e) {
if (e.model.isNew()) {
// clear out the shared object
itemForAdd = {};
}
},
cancel: function(e) {
if (e.model.isNew()) {
// clear out the shared object
itemForAdd = {};
}
}
With the previous changes, the functionality that you want is mostly working but the data in the table in the edit popup doesn't show the updated values. This is because the Kendo data bindings apparently didn't know they had to update. I couldn't figure out how to make that work, so I just used the AngularJs style bindings for that table (where you had +=itemNo=+), so that the values in the table would update based on the changes in the model object:
<tbody>
<tr>
<td>{{dataItem.itemNo}}</td>
<td>{{dataItem.itemDescr}}</td>
<td>{{dataItem.cat}}</td>
<td>{{dataItem.mfg}}</td>
<td>{{dataItem.mfgPartNo}}</td>
</tr>
</tbody>
But there was one more issue at this point, only the itemNo was being updated, not the itemDescr and that was because itemDescr was set as editable: false in your grid configuration, so I had to changed it to editable: true
fields: {
id: { type: "string", editable: false },
itemDescr: { type: "string", editable: true },
...
},
And finally, here is an updated plunker with my changes: http://plnkr.co/edit/rWavvMh4dRFAsJjuygQX?p=preview
I would like to filter the results.
There is a list of wines, my wish is when no checkbox is checked, the entire list of wine is displayed.
when only 1 checkbox is checked is displayed the related category
when more than one checkbox are checked the related categories are displayed
I'm a newbie to AngularJS, I tried with ng-model wihout success, here is the code without ng-model associated to the function:
<html ng-app="exampleApp">
<head>
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.10/angular.min.js"></script>
<script>
angular.module("exampleApp", [])
.controller("defaultCtrl", function ($scope) {
$scope.wines = [
{ name: "Wine A", category: "red" },
{ name: "Wine B", category: "red" },
{ name: "wine C", category: "white" },
{ name: "Wine D", category: "red" },
{ name: "Wine E", category: "red" },
{ name: "wine F", category: "white" },
{ name: "wine G", category: "champagne"},
{ name: "wine H", category: "champagne" }
];
$scope.selectItems = function (item) {
return item.category == "red";
};
$scope.selectItems = function (item) {
return item.category == "white";
};
$scope.selectItems = function (item) {
return item.category == "champagne";
};
});
</script>
</head>
<body ng-controller="defaultCtrl">
<h4>red: <input type="checkbox"></h4>
<h4>white: <input type="checkbox"></h4>
<h4>champagne: <input type="checkbox"></h4>
<div ng-repeat="w in wines | filter:selectItems">
{{w.name}}
{{w.category}}
</div>
</body>
</html>
How to use ng-model or ng-change to associate a function to each checkbox button to have a real time filtering model??
There are several implementations possible. Here's one:
Have a $scope.filter = {} object to hold the state of each filter. E.g. {red: true, white: false...}.
Associate each checkbox with the corresponding property using ng-model. E.g.: input type="checkbox" ng-model="filter['red']" />.
Have a function (e.g. $scope.filterByCategory(wine)) that decides if a wine should be displayed or not (based on the $scope.filter object).
Use that function to filter the items based on their category. E.g. <div ng-repeat="wine in wines | filter:filterByCategory">
The filterByCategory function could be implemented like this:
function filterByCategory(wine) {
// Display the wine if
var displayWine =
// the wine's category checkbox is checked (`filter[category]` is true)
$scope.filter[wine.category] || // or
// no checkbox is checked (all `filter[...]` are false)
noFilter($scope.filter);
return displayWine;
};
where noFilter() is a function that checks if there is any filter activated (and returns true if there is none):
function noFilter(filterObj) {
return Object.
keys(filterObj).
every(function (key) { return !filterObj[key]; });
}
See, also, this short demo.
UPDATE:
I created a modified version, which supports multiple filters (not just filtering by category).
Basically, it dynamically detects the available properties (based on the first wine element), adds controls (groups of check-boxes) for applying filters based on each property and features a custom filter function that:
Filters each wine item, based on every property.
If a property has no filter applied (i.e. no check-box checked), it is ignored.
If a property has check-boxes checked, it is used for filtering out wine items (see above).
There is code for applying multiple filters using AND (i.e. all properties must match) or OR (at least one property must match).
See, also, this updated demo.
Just to add onto #gkalpak answer, I found this codepen which allows you to provide the total amount left after an option is selected for each category.
Change the ng-repeat from:
<div ng-repeat="wine in (ctrl.wines | filter:ctrl.filterByProperties) as filteredWines">
{{ wine.name }} <i>({{ wine.category }})</i>
</div>
To
<div ng-repeat="wine in filtered = (ctrl.wines | filter:ctrl.filterByProperties) as filteredWines">
{{ wine.name }} <i>({{ wine.category }})</i>
</div>
And with the input labels add:
<label>
<input type="checkbox" ng-model="ctrl.filter[prop][value]" />
{{ value }}({{(filtered | filter:value:true).length}})
</label>
I prefer use filter as $filter
app.filter('someFilter',checkboxFilter)
checkboxFilter() {
return function (arr,filter,key,noOne=false) {
// arr is an array of objects
// filter is checkbox filter. someting like {1:true,2:false}
// key is a property in ech object inside arr
// noOne is a behavior if none of checkbox is activated (default:false)
if (!arr.length) return null;
function noOneCheck(filter) {
return Object.keys(filter).every((key) => {
return !filter[key]
})
}
return arr.filter((i) => {
return filter[i[key]] || (noOne && noOneCheck(filter))
})
}
};
html:
ng-repeat="u in project.projectTeamInvite | checkbox:project.status:'status' track by $index">