How to use Angular directive in Salesforce - angularjs

How to use angular directive in Salesforce
My directive html page
<apex:page showHeader="false" sidebar="false" standardStylesheets="false" applyHtmlTag="false">
<td>
<div class="address-container">
<p data-once-text="addr.company"></p>
<p><span class="once-addr" data-once-text="addr.city"></span>, <span class="once-addr" data-once-text="addr.state"></span></p>
<p>Remove</p>
</div>
</td>
</apex:page>
My directive call
mydirective.directive('shipmentAddress', ['CartService', function(CartService){
return{
scope: true,
replace: true,
templateUrl: 'apex/shipment_addresses_tplhtml',
controller: function($scope){
this.addressInfo = $scope.addr;
$scope.removeAddress = function(accountId, addrId){
if(confirm('Are you sure you want to remove this shipping address?')){
CartService.deleteCartAddress(accountId, addrId).then(function(response){
console.log(response);
$scope.$emit('refreshCart');
});
}
}
}
}
}]);
in my index.html
<tr class="addresses">
<td shipment-address ng-repeat="addr in acc.addresses" ng-if="addr.added == true"></td>
</tr>
But I am getting error in SaleForce/VisualForce as Attribute name "shipment-address" associated with an element type "td" must be followed by the ' = ' character.

Just do it like this:
<tr class="addresses">
<td shipment-address="true" ng-repeat="addr in acc.addresses" ng-if="addr.added == true"></td>
</tr>
That should remove the error. Empty string did not work for me but some value there will do it.

Related

Pass parameter outside of AngularJS directive into HTML

This is the problem: I want to sort a table by clicking on a table header. To avoid repeating code every , I have made a directive. The table headers show up nicely but I cannot find a way to make them sortable.
This is (part of) my HTML:
<div class="table-responsive" >
<table class="table table-striped" >
<thead>
<tr>
<th> </th>
<th><t-header name="vnaam" hoofd="voornaam" ></t-header></th>
<th><t-header name="anaam" hoofd="achternaam"></t-header></th>
</tr>
</thead>
<tbody>
<tr dir-paginate="cursist in homeCtrl.ckaart | orderBy: homeCtrl.sortKey:!homeCtrl.reverse" current-page="homeCtrl.currentPage">
<td><a ng-click="homeCtrl.gotoDetail(cursist.id)"><span ng-class="cursist.keuzemotivatie.length || cursist.leerdoelen.length ? 'infosign-true' : 'infosign-false'" class="fa fa-info-circle infosign"></span></a></td>
<td>{{cursist.vnaam}}</td>
<td>{{cursist.anaam}}</td>
</tr>
</tbody>
My directive:
.directive('tHeader', function(){
return {
restrict: 'EA',
scope: {
name: "#",
hoofd: "#"
},
templateUrl: 'templates/theader.html',
controllerAs: 'vm',
bindToController: true,
controller: function() {
var vm = this;
vm.sortKey = '-instrument';
// sort t.b.v. table sorting
vm.sort = function(keyname) {
// alert(keyname);
vm.sortKey = keyname;
vm.reverse = !vm.reverse;
console.log(vm.sortKey);
}
}
}
})
And the template belonging to the directive:
<div ng-click="vm.sort(vm.name)">{{vm.hoofd}}
<span ng-show="vm.sortKey === vm.name" ng-class="{ 'fa fa-chevron-up':vm.reverse, 'fa fa-chevron-down':!vm.reverse }"></span>
</div>
It seems to me that the 'vm.sortKey' parameter as well as the 'vm.reverse' parameter are not being passed into the HTML.
Anyone an idea? What mistake do I make?

How to display a textbox in place of text in a column in a table on button-click in angularjs

I am trying to create a small angular and php app. I want to display table and be able to edit it by displaying textbox in place of the old text on the click of a button. Can you please help me with the same. Thanks in advance
This is my controller
angular.module('directiveModule').controller('HomeController',['fetchServerData',function (fetchServerData) {
var ctrl = this;
ctrl.stateVal = false;
ctrl.getTableData = function () {
fetchServerData.getStudentsData()
.then(
function (response) {
ctrl.tableData =response.data;
},
function (response) {
console.log(response);
}
)
};
ctrl.init = function () {
ctrl.getTableData();
};
ctrl.init();
ctrl.editPrice = function () {
ctrl.stateVal = true;
};
}]);
This is the controller html
<table class="table table-striped">
<thead>
<tr>
<th>Flowers</th>
<th>Price</th>
<th>Actions</th>
</tr>
</thead>
<tbody ng-repeat="flower in home.tableData">
<tr>
<td>{{flower.name}}</td>
<td click-to-edit price="flower.price" stateVal="home.stateVal"></td>
<td><button><span class="glyphicon glyphicon-pencil" title="Edit Price" ng-click="home.editPrice()"></span></button></td>
</tr>
</tbody>
</table>
I am using a directive to implement the replacement
angular.module('directiveModule').directive('clickToEdit',[function () {
return{
scope: {
price : '=',
stateVal : '='
},
templateUrl: 'templates/directiveTemplates/clickToEdit.html',
restrict : 'EA',
link: function (scope, elem, attrs) {
scope.edit = scope.stateVal;
}
}
}]);
directive html
<div>
<span ng-hide="edit">
{{price}}
</span>
<div ng-show="edit">
<input class="inputText" type="text"/>
<div class="glyphicon glyphicon-ok" ng-click="save()"></div>
<div class="glyphicon glyphicon-remove" ng-click="cancel()"></div>
</div>
</div>
So this is my code, but the textbox does not appear on ng-click of the edit-pencil
Finally this is my json response
[{"name":"Lilies","price":200},{"name":"Carnations","price":200},{"name":"Roses","price":200},{"name":"Orchids","price":200},{"name":"Tulips","price":200}]
Please help me make it work
The following observations need to be corrected in your code
The attribute name stateVal should be state-val
a) You should keep a watch on your scope.stateVal if you want to scope.edit to be effected when click happened.
Or
b) You can use ng-hide="stateVal" in clickToEdit.html instead of ng-hide="edit".
The click event of the button should be called with flower variable inorder to isolate each edit of the row
<!-- HTML -->
<button ng-click="home.editPrice(flower)"><span class="glyphicon glyphicon-pencil" title="Edit Price">Edit</span></button>
/* Controller */
ctrl.editPrice = function (flower) {
flower.stateVal = true;
};
You can find the working code with above mentioned changes made in the following URL
Click here
Or
https://plnkr.co/edit/ve6AAewoKAtuUHWczaDG?p=preview
You have error in :
<td click-to-edit price="flower.price" stateVal="home.stateVal"></td>
property must by lowercase letters with - (snake case):
<td click-to-edit price="flower.price" state-val="home.stateVal"></td>
stateVal - > state-val

How do i append my attribute to a element in my Angular directive

I have a table in a template I want to populate with different data. My approach is using directives in Angular. I managed to make a template out of my table but I have no idea how to apply the value for the ng-repeat attribute from my html.
Here's a part of my index.html
<div id='unannounced' kc-item-table>
</div>
And here's a part of my template
<table class='table'>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr ng-repeat='item in changableItemList'>
<td>{{item.name}}</td>
<td>{{item.description}}</td>
</tr>
</tbody>
</table>
Heres my directive
app.directive('kcItemTable', function() {
return {
restrict: 'E',
templateUrl: 'scripts/controllers/itemTableTemplate.html'
}
})
So in order to reuse the template I want to be able to change the
ng-repeat='item in itemList'
But I have no idea how to append it to right element.
Here is the simple explaination with your code./
Your html template -
<table class='table'>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr ng-repeat='item in changableItemList'>
<td>{{item.name}}</td>
<td>{{item.description}}</td>
</tr>
</tbody>
</table>
Directive-With an isolate Scope
app.directive('kcItemTable', function() {
return {
restrict: 'E',
scope :{
itemList :'='
},
templateUrl: 'scripts/controllers/itemTableTemplate.html'
}
})
You can use directive with different list --
<div id='unannounced' kc-item-table item-list='ItemList1'>
</div>
<div id='unannounced' kc-item-table item-list='ItemList2'>
</div>
What you are trying to do is a very basic feature of AngularJS: data-binding to directives.
Check out the documentation about directives: https://docs.angularjs.org/guide/directive
Here is a very basic example forked from the above docs:
Main template:
<div my-customer name="naomi"></div>
<div my-customer name="boby"></div>
Directive:
.directive('myCustomer', function() {
return {
scope: {
name: "#"
},
template: 'Name: {{name}}'
};
});
http://plnkr.co/edit/r9tIzwxCFyEyAU3NX0G1?p=preview
To clarify, what you need in your case is a "scope" property on your directive. You will be able to pass the scope values through the DOM element attributes.
Thats easy just add this to your div where you add your attribute directive.
<div ng-controller="YourCustomController" id='unannounced' kc-item-table>
</div>
then in YourCustomController you would put a $scope property called.
$scope.changableItemList;
Or if you want multiple of these directives on the same page you can work with an isolated scope and do :
<div id='unannounced' kc-item-table customList='customList2'/>
<div id='unannounced' kc-item-table customList='customList1'/>
and in your directive do:
//you will need a controller above this which has $scope.customList declared
app.directive('kcItemTable', function() {
return {
restrict: 'E',
scope :{
customList :'=' //isolated scope with customList passed in
},
templateUrl: 'scripts/controllers/itemTableTemplate.html'
}
})

limit the character to 10 for filter text-field - ngTable

I have created an application using angularjs and ngTable with filer feature, the application is working fine also the filtering, but the filtering text-field should accept only 10 characters according to my requirement
Can anyone please tell me how to limit the character to 10 for that text-field, my code is as given below:
JSFiddle
script
$scope.tableParams = new ngTableParams({
page: 0,
count: 0
}, {
total: 0,
counts:[],
getData: function ($defer, params) {
// use build-in angular filter
var orderedData = params.filter() ? $filter('filter')(data, params.filter()) : data;
$defer.resolve(orderedData);
}
});
html
<div ng-app="main" ng-controller="DemoCtrl">
<table ng-table="tableParams" show-filter="true" class="table">
<tr ng-repeat="user in $data">
<td data-title="'Name'" filter="{ 'name': 'text' }">{{user.name}}</td>
<td data-title="'Age'">{{user.age}}</td>
</tr>
</table>
</div>
You can't do that easily with the directives provided by ng-table.
In order to achieve that, you must create your own input filterer, apply it on the ng-repeat and use a simple directive which will limit the caracteres of the input field.
Here is a working example, hope it will help you.
fiddle
HTML:
<div ng-app="main" ng-controller="DemoCtrl">
<table ng-table="tableParams" class="table">
<!-- first row with custom input filterer using the charLimit directive -->
<tr>
<td data-title="'Name'"><input char-limit="10" ng-model="textFilter"/></td>
<td data-title="'Age'"></td>
</tr>
<!-- declare the filter on your ng-repeat directive -->
<tr ng-repeat="user in $data | filter: { 'name': textFilter }">
<td>{{user.name}}</td>
<td>{{user.age}}</td>
</tr>
</table>
</div>
DIRECTIVE:
directive('charLimit', function(){
return {
scope: {
limit: '#charLimit',
model: '=ngModel'
},
require: 'ngModel',
restrict: 'A',
link: function($scope, $node) {
var limit = $scope.limit ? parseInt($scope.limit, 10) : 0;
$scope.$watch('model', function(val) {
if(limit>0 && !isNaN(limit))
$scope.model = $scope.model.slice(0,limit);
});
}
};
})
EDIT
An html5 attribute called maxlength can do it for you so you can avoid the directive and simply add this attribute to your input field

Nested Angular directives not working as expected

I have been making a directive to display some HTML and handle events as it seemed sensible to keep this code reusable. This directive was placed inside a ng-repeat and worked as expected.
Now I come to add some more display logic to it: 2 modes 'grid' and 'list', and create 2 ng-repeat elements for each mode. At this point the whole thing seems to fall apart with rendering doing some unexpected stuff.
I have created a Plunkr to demonstrate: http://plnkr.co/edit/GjxOjxE7KOlvYjxCqVJj?p=preview
App.js
var app = angular.module('myApp', []);
app.directive('documentObject', [function() {
return {
restrict: 'E',
transclude: true,
scope: {
object: '=',
viewmode: '=',
},
templateUrl: 'storage-object.html',
link: function(scope, element, attrs) {
if (scope.viewMode === 'grid') {
scope.class = 'grid-view';
} else {
scope.class = 'list-view';
}
}
}
}]);
app.controller('DocumentsController', ['$scope', function($scope) {
$scope.browser = {
viewMode: 'grid',
files: [{name: 'First'}, {name: 'Second'}, {name: 'Third'}]
};
}]);
index.html
<div ng-switch="browser.viewMode" class="filebrowser">
<div ng-switch-when="grid">
<div ng-repeat="file in browser.files">
<document-object viewmode="browser.viewMode" object="file"></document-object>
</div>
</div>
<table ng-switch-when="list">
<tr ng-repeat="file in browser.files">
<document-object viewmode="browser.viewMode" object="file"></document-object>
</tr>
</table>
</div>
storage-object.html
<div ng-if="viewmode == 'grid'" class="filebrowser {{ viewmode }}">
Grid Mode: {{ viewmode }}
<span class="file-label {{ class }}">{{ object.name }}</span>
</div>
<td ng-if="viewmode == 'list'" class="filebrowser {{ viewmode }}">
List Mode: {{ viewmode }}
<span class="file-label {{ class }}">{{ object.name }}</span>
</td>
Grid mode should only display the items as a grid, and list mode as a table. What is happening is grid mode is displaying everything and list mode is just rendering one element.
What is going on here?
This happens because you are not allowed to have anything else as a direct child of a <tr> than a <td> or <th> element.
In your case you are having a <document-object> element, which causes the browser to move it around (as it is not allowed to be where it is), which in turn confuses ng-switch.
Wrapping <document-object> in <td></td> and chenging it's template (e.g. replacing <td> with <div>), solves the problem.
index.html:
...
<table ng-switch-when="list">
<tr ng-repeat="file in browser.files">
<td>
<document-object viewmode="browser.viewMode" object="file"></document-object>
</td>
</tr>
</table>
storage-object.html:
...
<div ng-if="viewmode == 'list'" class="filebrowser {{ viewmode }}">
List Mode: {{ viewmode }}
<span class="file-label {{ class }}">{{ object.name }}</span>
</div>
See, also, this updated plunkr.
Please see here http://plnkr.co/edit/aMOsKAATd4aBl0swPik1?p=preview
you missed <td> tag
<table ng-switch-when="list">
<tr ng-repeat="file in browser.files">
<td> <!--here -->
<document-object viewmode="browser.viewMode" object="file"></document-object>
</td>
</tr>
</table>

Resources