Custom directive is not working/rendering the html on the browser - angularjs

I have created a custom directive but when I try to render it on browser it is not working.Please see my code and guide me if you can see where I went wrong.
Below is my code
JS
var app = angular.module('main',[]);
app.controller('servicecntr', function ($scope) {
$scope.name='jagdish';
$scope.changeclick= function(){
$scope.name= $scope.name.split('').reverse().join('');
}
})
app.directive('myDirectives', function(){
return{
restrict:'EA',
scope:false,
template: "<div> this is the print out of name {{name}}" + "onclick the modelPannel is <input type='text' ng-model='name'",
}
})

change the scope:true,you are inherited the scope from the parent controller, you are trying to access the name from parent controller,and how you use this directive in html,i don't find that code.

Related

Using sweetalert 2 with custom html and AngularJS

I am using SweetAlert2 with AngularJS, using this port to AngularJS 1.x : https://github.com/socialbase/angular-sweetalert-2.
I am trying to add some custom html in my swal, so when I do this:
angular.module('app').controller('TestController', function($scope, SweetAlert) {
$scope.test = "My test";
SweetAlert.swal({
type: 'warning',
html: '<input type="text" ng-model="test">'
}).then(function() {
});
});
It binds the html correctly, but it isn't binding ng-model using my variable test. Apparently it is putting the swal modal code outside my ng-controller in my html code.
How can I make my variable test work with AngularJS and SweetAlert?
Look at the code for this lib:
https://github.com/socialbase/angular-sweetalert-2/blob/master/lib/angular-sweetalert2.js
As you can see there is very little angular-related "porting", it's just a wrapper to the plain-JS library.
Therefore, it's simply not possible to put in your angular-specific code as a html and expect it to work.
However, looking at this lib's code examples, you could read html input's values after the dialog is closed.
angular.module('app').controller('TestController', function($scope, SweetAlert) {
$scope.test = "My test";
SweetAlert.swal({
type: 'warning',
html: '<input id="swal-input" type="text" ng-model="test">',
preConfirm: function() {
return document.getElementById('swal-input').value;
}
})
.then(function(value) {
$scope.test = value;
});
});

When unit testing a directive how to pass its controller

I am new to AngularJS and its unit test. Currently I am trying to test a directive with its controller in the template file:
It's template:
<div ng-controller = "SomeController" >
<select ng-model="data.selectedOption"
ng-options="data.code for data in data.availableOptions track by data.code">
</select>
</div>
It's js file:
angular.module('application.directives')
.directive('selector', function () {
return {
restrict: 'E',
templateUrl: 'templates.html'
};
});
Now I have a unit test like:
describe('selector', function () {
beforeEach(module('application.directives','application.templates'));
it('render the correct number of items', inject(function ($rootScope, $compile) {
var element = $compile('<selector></selector>')($rootScope);
$rootScope.$digest();
//I'd like to register the selector's controller here.
}));
});
In the test code, what would be the best way to register the controller? Do I need to create a mock one?
Thanks
If the controller SomeController is in the same module application.directives, you need not have to too anything. The controller will be available while testing the directive.
Here is the sample code in jsfiddle for similar case
If the controller is in different module.
Here is the sample code in jsfiddle for this case

Controller method not found when button inside template is pressed

I'm creating a project using NodeJS, Express and AngularJS that will have a search form (added via custom directive) and a search results that must be loaded only after the search button is pressed.
The problem is that the method I have created inside the controller can't be found from the search form.
Here is a sample of my code:
app.js
(function() {
var app = angular.module('app', ['app-directives']);
app.controller('AppController', function() {
this.buttonClick = function() {
alert('Test');
};
});
})();
directives.js
(function(){
var app = angular.module('app-directives', []);
app.directive('searchForm', function() {
return {
retrict: 'E',
templateUrl: '/partials/search-form.html'
};
});
app.directive('searchResults', function() {
return {
retrict: 'E',
templateUrl: '/partials/search-results.html'
};
});
})();
search-form.html
<input type="text" id="query" />
<button onclick="buttonClick">Search</button>
page-content.html
<section id="mainContent">
<search-form></search-form>
<search-results></search-results>
</section>
UPDATE
The second question will be posted in another thread.
About your first question:
You are using onclick attribute instead angular's 'ng-click' in the button search. This could be the problem. And do not forget to also add the 'ng-app' and 'ng-controller' tags. If not, your method will never be visible.
I also would recommend you to use $scope service instead of 'this' for attaching models and functions you later will use in your views.
Regards

Unable to locate FormController instance from parent scope

Problem
I'm trying to access an AngularJS FormController instance (created by setting a name property on a form directive) from it's parent controller scope. The output is undefined.
Confusion
But I can see the controller object as a property on the $scope when I log it to the console. I can also access the object from the template itself using the interpolation directive.
Example
The markup looks like:
<body ng-controller="FooCtrl">
<form name="FooForm" novalidate>
<input name="bar" required>
</form>
</body>
The JavaScript looks something like:
myAngularApp.controller('FooCtrl', function ($scope) {
console.log($scope.FooForm); // undefined
console.dir($scope); // has FooForm peek-a-booing in there
});
Demo
Here is the full plunk: http://plnkr.co/edit/EE7pdBF32B5XRbjZuy8R?p=preview
What am I doing wrong? I'm trying to follow these docs: https://docs.angularjs.org/api/ng/directive/form
The problem here is that your controller is initialized before your template, so at the time you are trying to use it, it's still undefined. Try this:
myApp.controller('MainCtrl', function ($scope) {
$scope.$watch('NewForm', function () {
var outputArea = document.getElementById('output-area');
outputArea.innerHTML = "The FormController instance is: " + $scope.NewForm;
});
});
Also note that using:
outputArea.innerHTML = "The FormController instance is: " + console.dir(newVal);
Doesn't make much sense, you're trying to concat the return value of console.dir to a string, which also always returns undefined ;) Changed it to:
outputArea.innerHTML = "The FormController instance is: " + $scope.NewForm;
Here's a working Plunker: http://plnkr.co/edit/yfVP8hD6saWV2tIok2ER?p=preview
Edit after comment:
If you want to be notified as soon as the form is available on your scope and you don't want to use $watch, you could do that by adding an custom directive to your form element which fires an event:
<form name="NewForm" novalidate formready>
The custom 'formready' directive:
.directive('formready', function(){
return {
restrict: 'A',
compile: function () {
return {
post: function(scope) {
scope.$emit('formready');
}
}
}
};
});
Now in your controller you can do:
$scope.$on('formready', function (event) {
console.log($scope.NewForm); // Available now
});
Here's a working example on Plunker: http://plnkr.co/edit/KG7LEB6EEkBkdONkL9LA?p=preview

Angular.js $compile returns array of html but not actual html

I have the following code:
app.directive('mySample', function($compile) {
return {
//template:"<input type='text' ng=model='sampleData'/> {{sampleData}} <br/>"
link: function(scope, element, atts, controller) {
var markup = "<input type='text' ng=model='sampleData'/> {{sampleData}} <br/>";
angular.element(element).html($compile(markup)(scope));
console.log($compile(markup)(scope));
}
};
});
And I would expect it to generate an input, some span that's coupled via the scope and a break. However I get this output:
[[object HTMLInputElement], [object HTMLSpanElement], [object HTMLBRElement]]
I also tried the template, in comment here, separately and then commenting out the link part. That generates the input and break elements but not the span that shows the coupled model input sampleData.
I have a non-working sample at http://jsfiddle.net/KvdM/nwbsT/ that demonstrates it.
Try this:
element.html(markup);
$compile(element.contents())(scope);
Running the function returned by the $compile service gives you DOM elements rather than html.
So you need to insert them into your page using append (or equivalent):
angular.element(element).append($compile(markup)(scope));
Maybe the easiest way is to use a hard-coded template rather than a dynamic generated one
<div ng-app="myApp">
<my-sample sample-data="'test'"></my-sample>
</div>
var app = angular.module('myApp', []);
app.directive('mySample', function ($compile) {
return {
restrict: 'E',
scope: {
sampleData: '=sampleData'
},
template: "<input type='text'/> {{sampleData}} <br/>",
};
});
FIDDLE
Depends on what kind of data should to be compiled, some times Angular returns a comment node type.
The relevant node that we want to use is the next() (its first sibling).
var tpl = '<div class="myWidget" ng-include="'templates/myWidget.html'"></div>;
var _myWidget = $compile(tpl)(scope);
var myWidget = null;
scope.$on('$includeContentLoaded', function () {
myWidget = _myWidget.next();
});
You just needed to add the jquery to use ".html" and fixed the naming of ng-model

Resources