I have a directive called DisplayAddress which takes in the address .I am using the isolalted scope and the Code performs the checking if the addres fields are blank or not and builds the Object whihc i am displaying it on the view
I have put the View in the code But now the problem arises when i use the one way binding the code throws error with parse string having error:syntax
Syntax Error .
return {
templateUrl: () => {
return "/app/Templates/Common/DisplayAddress"
},
restrict: "E",
replace: true,
scope: {
address: '='
},
controller: "DisplayAddressController",
controllerAs: "vm"
}
<div>
<div class="m-space">
<i class="fa fa-map-marker"></i>
<span data-ng-if="address.AddressType" data-ng-bind="address.AddressType"></span>
<span>{{vm.addressToString()|| ""}}</span>
</div>
<div class="row-m-box">
<span class="m-box" data-ng-if="address.Phone1"><i class="fa fa-phone"></i> <span class="label-content" data-ng-bind="address.Phone1"></span></span>
<span class="m-box" data-ng-if="address.Phone2"> <i class="fa fa-phone"></i> <span class="label-content" data-ng-bind="address.Phone2"></span></span>
<span class="m-box" data-ng-if="address.Fax"> <i class="fa fa-fax"></i> <span class="label-content" data-ng-bind="address.Fax"></span></span>
<span class="m-box" data-ng-if="address.Email"> <i class="fa fa-envelope"></i> <span class="label-content" data-ng-bind="address.Email"></span></span>
</div>
I want to make this directive with least number of watchers and single way bind .what can i do to make this directive a quality code
Related
I just encounter a problem I have written a directive but its not getting update, I dont know why, in console it does change but in directive it does not.
Here is my directive
mainControllers.directive('mallsproduct', function () {
return {
restrict: 'E',
scope: {
productInfo: '=info',
linkid: '=linkid'
},
templateUrl: 'directives/dashboard_product.html'
};
});
Here is my `html`
<div class="aa-properties-content-body mg-7" ng-controller="DashboardController as ctrl">
<ul class="aa-properties-nav aa-list-view">
<li style="border: 1px solid #ccc;margin-bottom: 25px;" ng-repeat="active_products in productInfo.items">
<article class="aa-properties-item mg-top-0-notimp">
<a class="aa-properties-item-img" href="#/product/{{active_products.id}}">
<img ng-if="active_products.photos[0].path" resize-image alt="img" class="" src="{{active_products.photos[0].path}}">
<img ng-if="!active_products.photos[0].path" resize-image class="" src="img/default_product.jpg" alt="">
</a>
<div class="aa-properties-item-content">
<div class="aa-properties-about padding-0-notimp">
<h5>{{active_products.name| limitTo : 10}}{{active_products.name.length > 10 ? '...' : ''}}</h5>
<p class="font-size-11-imp"><i class="fa fa-building-o" aria-hidden="true"></i> {{active_products.mall.name| limitTo : 10}}{{active_products.mall.name.length > 10 ? '...' : ''}}</p>
<p class="font-size-11-imp"><i class="fa fa-map-marker" aria-hidden="true"></i> {{active_products.mall.address| limitTo : 10}}{{active_products.mall.address.length > 10 ? '...' : ''}}</p>
<p class="font-size-11-imp"><i class="fa fa-phone" aria-hidden="true"></i> {{active_products.shop.telephone}}</p>
<p class="font-size-11-imp" ng-if="linkid == 3"><i class="fa fa-eye" aria-hidden="true"></i> {{active_products.views}}</p>
<div class="modal-demo">
<script type="text/ng-template" id="myModalContent.html">
<div ng-include src="'partials/update_product.html'"></div>
</script>
<div ng-controller="AddProductController">
<button ng-click="view_product(active_products.id)"><i class="fa fa-pencil" aria-hidden="true"></i></button>
<button ng-click="del_product(active_products.id)"><i class="fa fa-trash-o" aria-hidden="true"></i></button>
<button ng-if="linkid == 2" ng-init="status = 1" ng-click="reactivate_product(active_products.id, status)"><i class="fa fa-lock" aria-hidden="true"></i></button>
</div>
<div class="modal-parent">
</div>
</div>
</div>
</div>
</article>
</li>
</ul>
<div class="aa-title pad-top-30" ng-if="linkid == 1">
<p>Global page count for active product is {{global_pagecount}} and active product count from API is {{productInfo._meta.pageCount}}</p>
<h3 ng-if="global_pagecount < productInfo._meta.pageCount" class="text-align-center color-feroz cursor-pointer" ng-click="load_more(global_pagecount, linkid)">{{$root.translated_labels.dashboard.load_more}}</h3>
</div>
<div class="aa-title pad-top-30" ng-if="linkid == 3">
<p>Global page count for most viewed is {{global_pagecount_mostv}} and most viewed count from API is {{productInfo._meta.pageCount}}</p>
<h3 ng-if="global_pagecount_mostv < productInfo._meta.pageCount" class="text-align-center color-feroz cursor-pointer" ng-click="load_more(global_pagecount_mostv, linkid)">{{$root.translated_labels.dashboard.load_more}}</h3>
</div>
</div>
I am including directive in dashboard partial like this
<div class="active tab-pane" ng-if="linkid === '1'">
<malls-product info="active_products" linkid="linkid"></malls-product>
</div>
<!--Active products list ends here -->
<!-- Get Inactive Products -->
<div class="active tab-pane" ng-if="linkid === '2'" >
<malls-product info="$root.inactive_products" linkid="linkid"></malls-product>
</div>
<!--Get Inactive products ends here -->
<div class="active tab-pane" ng-if="linkid === '3'" >
<malls-product info="$root.mostviewed_products" linkid="linkid"></malls-product>
</div>
<!-- View Profile-->
and This is the api which does show the result in console.
$scope.global_pagecount = 1;
$scope.active_product = function () {
$http.get($rootScope.baseurl + 'abc?&page=' + $scope.global_pagecount,
{headers:
{'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': $rootScope.keyword_auth_token, 'Accept-Language': $cookies.get('type')}
})
.success(function (data) {
//$scope.active_product_pageCount = data._meta.pageCount;
if ($scope.global_pagecount === 1) //I know for sure the first page of pagination is 1
{
$scope.active_products = data;
}
if ($scope.global_pagecount > 1) // If user click load more global count gets incremented and new results push in active_producst
{
/* for loading new results Pagination Applied */
for (var times = data.items.length - 1; times >= 0; times--) {
$scope.active_products.items.push(data.items[times]);
}
}
console.log($scope.active_products);
})
.error(function (data) {
// console.log(data);
});
};
What is the issue, why it is not getting update, If I use rootscopethen it works fine, obviously it has too, but not with $scope.
Note : when scope.global_pagecount value is equal to 2 i get new results but not in directive only in console. By default scope.global_pagecount has value equal to 1.
You don't use your directive correctly. You define it as:
mainControllers.directive('mallsproduct'
Which means you should use it as:
<mallsproduct ..>
Or define your directive camelcased:
mainControllers.directive('mallsProduct'
Then you can use it as you do now:
<malls-product ..>
This is because of the Isolated scope doesn’t know anything about its parent scope. You just created a directive with an isolated scope.
To access any parent scope data, we need to pass the scope data to our directive explicitly. This is achieved by setting properties on the scope object in the DDO.
Another important thing is that, these properties also MUST be set as the attributes of the directive html element.
Im trying to create a directive for a button with a loading state using Bootstrap 3. When the button is disabled I get some strange style which I can't seem to identify. Below I included my code.
directive.js
function gfkLoadingButton(settings) {
return {
restrict: 'E',
transclude: true,
scope: {
isLoading: "=",
ngClass: "=",
ngStyle: "=",
loadingText: "=",
ngDisabled: '='
}
};
}
template.html
<button class="btn"
ng-class="ngClass"
type="button"
ng-disabled="ngDisabled"
ng-style="ngStyle">
<span ng-show="!isLoading">
<ng-transclude ng-disabled="ngDisabled"></ng-transclude>
</span>
<span ng-show="isLoading">
<i class="fa fa-spinner fa-pulse"></i>
{{loadingText}}
</span>
</button>
usage
<loading-button ng-class="'btn-primary'"
ng-style="{'width': '144px'}"
ng-disabled="addAdjustmentForm.$invalid || state.saving"
is-loading="state.saving"
loading-text="Saving">
<span class="glyphicon glyphicon-plus"></span>
Add Adjustment
</loading-button>
ngDisabled is an expression so it should be ngDisabled: '&' instead of '=', and in your template it should be ng-disabled = "ngDisabled()".
Someone pointed the solution out in the comments but deleted their comment shortly after. Either way, thank you unknown commenter, the solution was really simple. I just needed to include replace: true to the code.
directive.js
function loadingButton(settings) {
return {
restrict: 'E',
transclude: true,
replace: true,
scope: {
isLoading: "=",
loadingText: "=",
ngDisabled: '='
}
};
}
directive.html
<button class="btn"
type="button">
<span ng-show="!isLoading">
<ng-transclude ng-disabled="ngDisabled"></ng-transclude>
</span>
<span ng-show="isLoading">
<i class="fa fa-spinner fa-pulse"></i>
{{loadingText}}
</span>
</button>
usage
<loading-button ng-class="'btn-primary'"
ng-style="{'width': '143px'}"
ng-disabled="addCalculationForm.$invalid || state.saving"
is-loading="state.saving"
loading-text="'Saving'">
<span class="glyphicon glyphicon-plus"></span>
Add Adjustment
</loading-button>
I have a html file
<div class="list">
<a ui-sref="sideMenu.settings.profileSettings" class="item item-icon-left">
<i class="icon ion-email"></i></a>
User Profile
</a>
<a ui-sref="sideMenu.settings.profileSettings" class="item item-icon-left">
<i class="icon ion-email"></i>
Vehicle
</a>
</div>
and a js file
.state('sideMenu.settings.profileSettings', {
url: "/profileSettings",
templateUrl: "templates/Settings/profileSettings.html",
controller: 'profileSettingsController'
})
Now whenever I click on the state. It updates the url. It means it's executing but it doesn't update the view. I have beem scratching my head but can't seem to figure out what the problem is.
There is a working plunker. Not fully sure what is not working, because there are now really many resources and Q & A here revealing the mystery of the UI-Router... but ok
I used your states like this:
.state('sideMenu', {
url: "",
template: '<div ui-view></div>',
})
.state('sideMenu.settings', {
url: "",
template: '<div ui-view></div>',
})
.state('sideMenu.settings.profileSettings', {
url: "/profileSettings",
templateUrl: "templates/Settings/profileSettings.html",
controller: 'profileSettingsController'
})
.state('sideMenu.settings.vehicle', {
url: "/vehicle",
templateUrl: "tpl.html",
})
As we can see, I just showed the parents and added one another state vehicle.
And with the index.html like that:
<div class="list">
<a ui-sref="sideMenu.settings.profileSettings" class="item item-icon-left">
<i class="icon ion-email"></i>
User Profile
</a><br />
<a ui-sref="sideMenu.settings.vehicle" class="item item-icon-left">
<i class="icon ion-email"></i>
Vehicle
</a>
</div>
plus the target somewhere
<div ui-view=""></div> // here will be the parent state injected
It is working. Check it here
Is it possible to have a view per model , ie an edit view for an item, and only that view to be shown for this specific model?
I have a list of tasks, like a todo list. When I click an add button I want an edit view to be shown only for that list and not for every other list I have.
Sorry for my English and possible ignorance on terminology. I am new to Angularjs
My code:
index.html
<div ng-repeat="list in lists" jui-dg-list="{ handle: 'i.fa-arrows' }" class="md-whiteframe-z2 home-drag list" style="top: {{list.ui_top}}px; left: {{list.ui_left}}px;">
<md-subheader>{{list.name}}</md-subheader>
<md-list>
<md-item ng-repeat="task in list.tasks">
<md-item-content>
<div>
<span>{{task.description}}</span>
<span>{{task.completed}}</span>
<span>{{task.priority_id}}</span>
<i class="fa fa-trash-o" ng-click="deleteTask(task, list)"></i>
</div>
</md-item-content>
</md-item>
<div ui-view="newTask"></div>
<i class="fa fa-plus" ng-click="goToState('home.newTask', {id: list.id})"></i>
</md-list>
<i class="fa fa-times" ng-click="deleteList(list)"></i>
<i class="fa fa-arrows"></i>
</div>
app.js
$stateProvider.state('home', {
url: '/',
templateUrl: 'views/home.html',
controller: 'HomeCtrl',
resolve: {
notes: ['NotesLoader', function(NotesLoader){
return NotesLoader();
}],
lists: ['ListsLoader', function(ListsLoader){
return ListsLoader();
}]
}
});
$stateProvider.state('home.newTask', {
url: 'list/:id/task/create',
views: {
'newTask#home': {
templateUrl: 'views/home.newTask.html',
controller: 'NewTaskCtrl'
}
}
});
With this code when I click to add a new task the newTask view will be shown on every list and not on the list I clicked.
That's to be expected because inside to my ng-repeat I have <div ui-view="newTask"></div> so when I go to newTask state every ui-view with the name newTask will be shown.
Is there any way to achieve it only for the model that's was clicked ?
I'm new to Angular, but it seems to be the "Angular way" to avoid DOM manipulation whenever possible. I am not sure if I'm taking the right approach.
I have three buttons on the bottom (next,back, and home). These get enabled and disabled by way of the actions of other controllers. For example if a text box is NULL the next button will be disabled until something is entered. I have the following:
<div ng-controller="nextBackController" class="navbar navbar-app navbar-absolute-bottom">
<div class="btn-group justified">
<i class="fa fa-arrow-left fa-navbar" ng-class="{'btn-disabled' : btnBack}"></i> Back
<a id="btnHome" ng-click="handleClick()" href="#/" class="btn btn-navbar btn-icon-only btn-bounded" ng-class="{'btn-disabled' : btnHome}"><i class="fa fa-home fa-navbar"></i> Home</a>
Next <i class="fa fa-arrow-right fa-navbar" ng-class="{'btn-disabled' : btnNext}"></i>
</div>
</div>
And now for the JS:
app.service("nxtBackClick", function($rootScope, bottomButtonWatcher) {
this.btn = "";
this.broadcast = function(btn) {
//Toggle the Next button as an example
bottomButtonWatcher.btnNext = ~bottomButtonWatcher.btnNext;
//set the btn that is clicked
this.btn = btn;
$rootScope.$broadcast('bottomBtnClick');
};
});
app.service("bottomButtonWatcher", function($rootScope) {
//Set all these to disabled
this.btnHome = true;
this.btnNext = false;
this.btnBack = true;
});
And now the controller:
//####################### - Next Back Controller ########################
app.controller("nextBackController",
function($scope, nxtBackClick, bottomButtonWatcher){
$scope.btnHome = bottomButtonWatcher.btnHome;
$scope.btnNext = bottomButtonWatcher.btnNext;
$scope.btnBack = bottomButtonWatcher.btnBack;
$scope.handleClick = function(btn) {
nxtBackClick.broadcast(btn);
};
}
);
Having both a class attribute and an ng-class attribute can be problematic. They should both be condensed into a single ng-class attribute. You are already passing an object, so just add another property to it. Setting classes to always be shown is accomplished by setting their property to true.
<div ng-controller="nextBackController" class="navbar navbar-app navbar-absolute-bottom">
<div class="btn-group justified">
<a href="#/" class="btn btn-navbar btn-icon-only btn-bounded">
<i ng-class="{'fa fa-arrow-left fa-navbar': true, 'btn-disabled' : btnBack}"></i>
Back
</a>
<a id="btnHome" ng-click="handleClick()" href="#/" ng-class="{'btn btn-navbar btn-icon-only btn-bounded':true, 'btn-disabled' : btnHome}">
<i class="fa fa-home fa-navbar"></i>
Home
</a>
<a href="#/second" class="btn btn-navbar btn-icon-only">
Next
<i class="" ng-class="{'fa fa-arrow-right fa-navbar':true, 'btn-disabled' : btnNext}"></i>
</a>
</div>
</div>
You're using $rootScope.$broadcast but nobody is listening, you need to have a scope watcher in your controller that actually controls the buttons:
//####################### - Next Back Controller ########################
app.controller("nextBackController",
function($scope, nxtBackClick, bottomButtonWatcher){
$scope.btnHome = bottomButtonWatcher.btnHome;
$scope.btnNext = bottomButtonWatcher.btnNext;
$scope.btnBack = bottomButtonWatcher.btnBack;
$scope.handleClick = function(btn) {
nxtBackClick.broadcast(btn);
};
$scope.$watch('bottomBtnClick', function(buttonVal){
$scope[buttonVal] = true;
});
}
);