I'm trying to attach an angular directive to `
{
field:"stateID",
hidden: true,
title: "State",
editor: function (container, options) {
var _statesDirective = $('<div><my-states></my-states></div>');
_statesDirective.appendTo(container);
}`
My diretive looks like this:
appRoot.directive('myStates', function () {
return {
restrict: 'EA',
templateUrl: 'directivesHTML/ddStates.html',
scope:false,
controller: function ($scope)
{
var dsStates = new kendo.data.DataSource({
autoBind: false,
page: 1,
transport: {
read: {
url: "api/util/getStates",
dataType: "json"
}
},
schema: {
model: {
id: "stateID",
fields: {
stateID: { type: 'string' },
name: { type: "string" }
}
}
}
});
dsStates.read().then(function () {
$('#ddStates')
.kendoDropDownList({
dataTextField: "name",
dataValueField: "stateID",
dataSource: dsStates,
optionLabel: '--',
change: function (e) {
}
});
});
}
};
});
For some weird reason, it wont work, if I put the directive someplace else, any outside html page, it works just fine, but not from here. I thought it could be the version, upgraded it to the latest one for this month to no avail.
Any clues ?
-thanks,
You need to compile your html before appending it (using $compile service).
So in your editor: function,
// Specify what it is we'll be compiling.
var to_compile = '<div><my-states></my-states></div>';
// Compile the tag, retrieving the compiled output.
var _statesDirective = $compile(to_compile)($scope);
// Ensure the scope and been signalled to digest our data.
$scope.$digest();
// Append the compiled output to the page.
$compiled.appendTo(_statesDirective);
For more reference, Angular Docs for $compile
Also, how can we use $compile outside a directive in Angularjs
Related
I've been creating a number of small directives and using hard-coded arrays for testing while I build out functionality. Now that I've got some of that done, I went back and created a service to load the data from a website via JSON; it returns a promise and when it's successful I update the property my template is based off of. Of course, as soon as I did that my directive stopped rendering correctly.
What is the preferred way of binding my directive to asynchronously loaded data so that when the data finally comes back my directive renders?
I'm using Angular 1.4.7.
Here's a simple example of my hard-coded version.
angular
.module('app', []);
angular.module('app').controller('test', function(){
var vm = this;
vm.inv = 'B';
vm.displayInv = function () {
alert('inv:' + vm.inv);
};
});
angular.module('app')
.directive('inventorytest', function () {
return {
restrict: 'E',
template: '<select ng-model="ctrl.selectedOption" ng-options="inv.code as inv.desc for inv in ctrl.invTypes"></select>{{ctrl.sample}}. Selected: {{ctrl.selectedOption}}',
scope: { selectedOption: '='},
bindToController: true,
controller: function () {
this.invTypes = [
{ code: 'A', desc: 'Alpha' },
{ code: 'B', desc: 'Bravo' },
{ code: 'C', desc: 'Charlie' },
];
this.sample = 'Hello';
},
controllerAs: 'ctrl'
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.7/angular.js"></script>
<div ng-app="app" ng-controller="test as vm">
<inventorytest selected-option='vm.inv'></inventorytest>
<br/>
Controller: {{vm.inv}}
</div>
My service is essentially just a thin wrapper around an $http call, ex:
return $http({ method: 'GET', url: 'https://myurl.com/getinfo' });
And I had tried modifying my code to do something like:
this.invTypes = [ { code: '', desc: '' }];
ctrService.getInfo()
.then(function successCallback(response) {
this.invTypes = response.data;
}, function errorCallback(response) {
// display error
});
Like I said, that doesn't work since it seems Angular isn't watching this property.
Within the callback this has a different context and isn't what you want it to be.
You need to save a reference to the controller this and use that within any callbacks
// store reference to `this`
var vm = this;
vm.invTypes = [ { code: '', desc: '' }];
ctrService.getInfo()
.then(function successCallback(response) {
// must use reference to maintain context
vm.invTypes = response.data;
}, function errorCallback(response) {
// display error
});
Here is a plunker example of something that i'm trying to do:
http://plnkr.co/edit/dlktEzrBeFshGaZsTmg7?p=preview
Basically i just want to use jquery file upload inside the modal window. as you can see in the plunker though, none of the callbacks are being called.
$('#fileupload').fileupload({
dataType: 'json',
done: function (e, data) {
$log.log("done accessed");
},
fail: function (e, data) {
$log.log("fail accessed");
},
progressall: function (e, data) {
$log.log("progressall");
},
//add: function(e,data){
//$log.log("add accessed");
//},
submit: function (e, data) {
var notetext = $("#descModal").val();
data.formData = { Description: notetext };
$log.log("submit accessed");
}
even the 'add' callback isn't being called when i add a file. This all works fine if i use angular strap, but i'd rather not use that for other reasons. I've investigated the modal initialization, and tried to override the windowTemplateURL
var theModal = $modal.open({ scope: $scope, templateUrl: modURL, controller: 'detailController', size: 'lg' });
(the default of which is here: https://github.com/angular-ui/bootstrap/blob/master/template/modal/window.html ),and it looks like the problem is the 'modal-transclude' attribute. Any ideas on getting past this?
Upgrade jQuery-ui to version 1.9.0 or higher.
Never use jQuery selectors in your controller, write a directive. E.g.
angular.module("myapp").directive("fileUpload", function($log, $parse) {
return {
restrict: "A",
link: function(scope, element, attrs) {
var options = $parse(attrs.fileUpload)(scope) || {};
element.fileupload({
dataType: "json",
url: "your url",
done: function(e, data) {
$log.log("done accessed");
},
fail: function(e, data) {
$log.log("fail accessed");
},
progress: function(e, data) {
options.progress = parseInt(data.loaded / data.total * 100, 10);
scope.$apply();
$log.log("progress");
},
submit: function(e, data) {
$log.log("notetext:", options.notetext);
data.formData = {
Description: options.notetext
};
$log.log("submit accessed");
}
});
}
}
And use it in this way:
<input file-upload="fileUploadOptions" type="file" multiple data-sequential-uploads="true" />
Here's an updated plunker: http://plnkr.co/edit/qLckEIlNLEcIfvwn4Q5x?p=preview
btw there is an example of the usage of this fileupload with angularjs: https://blueimp.github.io/jQuery-File-Upload/angularjs.html .
I have the following on an angular controller:
$scope.emailsConfig = {
valueField: 'email',
labelField: 'name',
options: [{email: 'brian#dn.cm', name: 'Brian'},
{email: 'nikola#tl.com', name: 'Nikola'}],
}
Then I have the following:
<select selectize="emailsConfig" ng-model="emails"></select>
This works fine ... But then I changed options to:
options: UserService.GetEmails()
This does not work. When I logged options and get:
{"Emails":[{email: 'brian#dn.cm', name: 'Brian'}, {email: 'nikola#tl.com', name: 'Nikola'}]}
How can I get the values that are in Emails?
I tried UserService.GetEmails().Emails but somehow get undefined
UPDATE
UserService.GetEmails() is the following:
application.service('UserService', function ($http) {
return {
GetEmails: function () {
return $http.get('api/users/emails');
}
}
}
The service is returning the promise that $http returns. You still need to add the callback that returns the data. Can use success() or then()
Try this:
UserService.GetEmails().success(function(resp){
$scope.emailsConfig = {
valueField: 'email',
labelField: 'name',
options: resp.Emails
}
}).error(function(){
alert('Ooops')
});
to move more of this into the service and out of the controller you could do something like:
application.service('UserService', function ($http) {
return {
GetEmails: function (callback) {
$http.get('api/users/emails').success(function (resp) {
var config = {
valueField: 'email',
labelField: 'name',
options: resp.Emails
}
callback(config);
}).error(function () {
alert('Oooops');
});
}
}
}
then in controller
UserService.GetEmails(function(emailsConfig){
$scope.emailsConfig = emailsConfig;
})
I'm making an Angular App and I'm starting to use some of the Kendo UI controls. I'm having some issues wiring up the AutoComplete control. I would like to use a factory that will return the list of "auto complete" values from my database.
I have iincluded the auto complete control and I'm trying to use the k-options attribute:
<input kendo-auto-complete ng-model="myFruit" k-options="FruitAutoComplete" />
In my controller the following hard coded list of fruits work:
$scope.FruitAutoComplete = {
dataTextField: 'Name',
dataSource:[
{ id: 1, Name: "Apples" },
{ id: 2, Name: "Oranges" }
]
}
When I move this over to use my factory I see it calling and returning the data from the factory but it never get bound to the screen.
$scope.FruitAutoComplete = {
dataTextField: 'Name',
dataSource: new kendo.data.DataSource({
transport: {
read: function () {
return FruitFactory.getYummyFruit($scope.myFruit);
}
}
})
}
I end up with the request never being fulfilled to the auto complete.
My factory is just returning an array of fruit [
my Fruit Factory Code:
getYummyFruit: function (val) {
return $http.get('api/getFruitList/' + val)
.then(function (res) {
var fruits= [];
angular.forEach(res.data, function (item) {
fruits.push(item);
});
return fruits;
});
}
Here is your solution
http://plnkr.co/edit/iOq2ikabdSgiTM3sqLxu?p=preview
For the sake of plnker I did not add $http (UPDATE - here is http://plnkr.co/edit/unfgG5?p=preview with $http)
UPDATE 2 - http://plnkr.co/edit/01Udw0sEWADY5Qz3BnPp?p=preview fixed problem as per #SpencerReport
The controller
$scope.FruitAutoCompleteFromFactory = {
dataTextField: 'Name',
dataSource: new kendo.data.DataSource({
transport: {
read: function (options) {
return FruitFactory.getYummyFruit(options)
}
}
})
}
The factory -
factory('FruitFactory', ['$http',
function($http) {
return {
getYummyFruit: function(options) {
return $http.get('myFruits.json').success(
function(results) {
options.success(results);
});
}
}
}
Until now, I have been querying the data stores using Rally App SDK, however, this time I have to update a story using the js sdk. I tried looking up for examples for some sample code that demonstrates how the App SDK can be used to update/add values in Rally. I have been doing CRUD operations using Ruby Rally API but never really did it with the app sdk.
Can anyone provide some sample code or any link to where I could check it out?
Thanks
See this help document on updating and creating reocrds. Below are examples - one updates a story, the other creates a story. There is not much going on in terms of UI: please enable DevTools console to see console.log output.
Here is an example of updating a Defect Collection on a User Story:
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
launch: function() {
console.log("launch");
Rally.data.ModelFactory.getModel({
type: 'User Story',
success: this._onModelRetrieved,
scope: this
});
},
_onModelRetrieved: function(model) {
console.log("_onModelRetrieved");
this.model = model;
this._readRecord(model);
},
_readRecord: function(model) {
var id = 13888228557;
console.log("_readRecord");
this.model.load(id, {
fetch: ['Name', 'Defects'],
callback: this._onRecordRead,
scope: this
});
},
_onRecordRead: function(record, operation) {
console.log('name...', record.get('Name'));
console.log('defects...', record.get('Defects'));
if(operation.wasSuccessful()) {
//load store first by passing additional config to getCollection method
var defectStore = record.getCollection('Defects', {
autoLoad: true,
listeners: { load: function() {
//once loaded now do the add and sync
defectStore.add({'_ref':'/defect/13303315495'});
defectStore.sync({
callback: function() {
console.log('success');
}
});
}}
});
}
},
});
Here is an example of creating a user story, setting a project and scheduling for an iteration:
Ext.define('CustomApp', {
extend: 'Rally.app.TimeboxScopedApp',
componentCls: 'app',
scopeType: 'iteration',
comboboxConfig: {
fieldLabel: 'Select an Iteration:',
labelWidth: 100,
width: 300
},
addContent: function() {
this._getIteration();
},
onScopeChange: function() {
this._getIteration();
},
_getIteration: function() {
var iteration = this.getContext().getTimeboxScope().record.get('_ref');
console.log('iteration',iteration);
if (!this.down('#b2')) {
var that = this;
var cb = Ext.create('Ext.Container', {
items: [
{
xtype : 'rallybutton',
text : 'create',
id: 'b2',
handler: function() {
that._getModel(iteration);
}
}
]
});
this.add(cb);
}
},
_getModel: function(iteration){
var that = this;
Rally.data.ModelFactory.getModel({
type: 'UserStory',
context: {
workspace: '/workspace/12352608129'
},
success: function(model) { //success on model retrieved
that._model = model;
var story = Ext.create(model, {
Name: 'story 777',
Description: 'created via appsdk2'
});
story.save({
callback: function(result, operation) {
if(operation.wasSuccessful()) {
console.log("_ref",result.get('_ref'), ' ', result.get('Name'));
that._record = result;
that._readAndUpdate(iteration);
}
else{
console.log("?");
}
}
});
}
});
},
_readAndUpdate:function(iteration){
var id = this._record.get('ObjectID');
console.log('OID', id);
this._model.load(id,{
fetch: ['Name', 'FormattedID', 'ScheduleState', 'Iteration'],
callback: function(record, operation){
console.log('ScheduleState prior to update:', record.get('ScheduleState'));
console.log('Iteration prior to update:', record.get('Iteration'));
record.set('ScheduleState','In-Progress');
record.set('Iteration', iteration);
record.set('Project', '/project/12352608219')
record.save({
callback: function(record, operation) {
if(operation.wasSuccessful()) {
console.log('ScheduleState after update..', record.get('ScheduleState'));
console.log('Iteration after update..', record.get('Iteration'));
}
else{
console.log("?");
}
}
});
}
})
}
});