Re-initialise directive on controller - html

I have a carousel that loads a bunch of items from an array, but a directive is being used to show the carousel.
I want to remove an item from a list such as "street parties" if something gets selected, but as the list of items seems to binded to a directive how can reload the directive? I have seen similar questions but I cant seem to get anything to work yet.. Thank you.
In my controller I have the various items like this
this.eventProducts.push({
link: "/quote/bar-and-bat-mitzvah-insurance",
image: "/Content/Images/policies/bar-mitzvah.jpg",
name: "Bar and Bat Mitzvahs"
});
this.eventProducts.push({
link: "/quote/street-party-insurance",
image: "/Content/Images/policies/street-party.jpg",
name: "Street Parties"
});
this.eventProducts.push({
link: "/quote/conference-and-meetings-insurance",
image: "/Content/Images/policies/conference.jpg",
name: "Conferences and Meetings"
});
Then I have this directive which sets the carousel
angular.module("App")
.controller("HomepageController", HomepageController)
.config(["$routeProvider", HomepageController.routing])
.directive("owlCarousel", () => {
return {
restrict: "E",
transclude: false,
link: (scope:any) => {
scope.initCarousel = (element) => {
// provide any default options you want
var defaultOptions = {
};
var customOptions = scope.$eval($(element).attr("data-options"));
// combine the two options objects
for (var key in customOptions) {
defaultOptions[key] = customOptions[key];
}
// init carousel
(<any>$(element)).owlCarousel(defaultOptions);
};
}
};
})
.directive("owlCarouselItem", [() => {
return {
restrict: "A",
transclude: false,
link: (scope, element) => {
// wait for the last item in the ng-repeat then call init
if (scope.$last) {
scope.initCarousel(element.parent());
}
}
};
}]);
And in the HTML the items are being loaded like this
<div class="row homepage-events">
<div class="homepage-heading"><h2 class="text-center">A Selection of our Most Popular Event Insurance Policies</h2></div>
<data-owl-carousel class="owl-carousel" data-options="{navigation: false, pagination: true, rewindNav : true}">
<div class="carousel-item" owl-carousel-item="" data-ng-repeat="product in ::homepageController.eventProducts">
<div class="">
<div class="thumbnails thumbnail-style thumbnail-kenburn">
<div class="thumbnail-img">
<div class="overflow-hidden">
<a class="" href="{{::product.link}}">
<img data-ng-src="{{::product.image}}" alt="{{::product.altText}}" />
</a>
</div>
<a class="btn-more2 hover-effect">Insurance for</a>
<a class="btn-more hover-effect" data-ng-href="{{::product.link}}">{{::product.name}}</a>
</div>
</div>
</div>
</div>
</data-owl-carousel>
</div>

Related

Vue.js - Search function for JSON Object

I am new to Vue.js, and I want to add a search function for my site. The data is from an API Call and is displayed using vue.js too.
Display HTML Code:
<div class="row" v-for="items in data">
<div class="col-lg-4 col-md-6" data-toggle="modal" data-target="#exampleModal" user="'items'" #click="sendInfo(items)">
<a href="#" class="latest-product__item">
<div class="latest-product__item__pic">
<img src="img/item_image_placeholder.jpg" alt="">
</div>
<div class="latest-product__item__text">
<h6>{{items.item_name}}</h6>
<div v-for="variant in items.variants">
<div v-for="store in variant.stores">
<span>{{store.default_price}}</span>
</div>
</div>
</div>
</a>
</div>
And here's my Vue.js:
window.onload = function () {
const access_token = "";
new Vue({
el: '#item-data',
data () {
return {
data:[],
selectedUser:'',
itemCart: [],
search:'',
quantity: '',
cartCheckout: []
}
},
mounted () {
axios.get('**api call here**', {
headers : {
Authorization: 'Bearer ' + access_token
},
params: {
limit: 250
}
})
.then((response) => {
// handle success
this.data = response.data.items
console.log(response);
removeLoader();
})
.catch(function (error) {
// handle error
console.log(error);
})
.then(function () {
});
},
computed:{
cartItem(){
return store.getters.printCart;
},
count(){
return store.state.cartCount;
},
},
methods:{
sendInfo(items) {
this.selectedUser = items;
},
addCart: function(cartdets){
store.commit('addCart', cartdets);
store.commit('addCount', 1);
}
}
})
}
What I want now is to add a search function to my displayed items. I already added v-model to my input tag. The items are dynamically displayed using vue and I want a search function for specific items.
You could create a computed property, maybe name it something like filteredItems, and make it loop through all of your items and save the items you want to display into an array and then return that array.
Then in your html use a v-for to display the items from filteredItems.

Vuejs component does not render immediately

I have a vue app and a component. The app simply takes input and changes a name displayed below, and when someone changes the name, the previous name is saved in an array. I have a custom component to display the different list items. However, the component list items do not render immediately. Instead, the component otems render as soon as I type a letter into the input. What gives? Why would this not render the list items immediately?
(function(){
var app = new Vue({
el: '#app',
components: ['name-list-item'],
data: {
input: '',
person: undefined,
previousNames: ['Ian Smith', 'Adam Smith', 'Felicia Jones']
},
computed: {
politePerson: function(){
if(!this.person) {
return 'Input name here';
}
return "Hello! To The Venerable " + this.person +", Esq."
}
},
methods: {
saveInput: function(event){
event.preventDefault();
if(this.person && this.previousNames.indexOf(this.person) === -1) {
this.previousNames.push(this.person);
}
this.setPerson(this.input);
this.clearInput();
},
returnKey: function(key) {
return (key + 1) + ". ";
},
clearInput: function() {
this.input = '';
},
setPerson: function(person) {
this.person = person;
}
}
});
Vue.component('name-list-item', {
props: ['theKey', 'theValue'],
template: '<span>{{theKey}} {{theValue}}</span>'
});
})()
And here is my HTML.
<div id="app">
<div class="panel-one">
<span>Enter your name:</span>
<form v-on:submit="saveInput">
<input v-model="input"/>
<button #click="saveInput">Save</button>
</form>
<h1>{{politePerson}}</h1>
</div>
<div class="panel-two">
<h3>Previous Names</h3>
<div>
<div v-for="person, key in previousNames" #click='setPerson(person)'><name-list-item v-bind:the-key="key" v-bind:the-value="person" /></div>
</div>
</div>
</div>
You are not defining your component until after you have instantiated your Vue, so it doesn't apply the component until the first update.

Pagination with React.js

Right now I'm stuck with pagination implementation with React. I have all the neccessary data from JSON, however I got no result.
Here's the code I use:
first, I fetch data from the server:
constructor() {
super();
this.state = {items: {}, totalPages: [], nextPage: []};
}
componentDidMount() {
let url = 'http://localhost:8000/items?json=true';
request.get(url).then((response) => {
this.setState({
items: response.body.items.data,
totalPages: response.body.items.last_page,
nextPage: response.body.items.next_page_url
});
});
}
Thus I get a simple JSON file:
{
"items": {
"total": 26025,
"per_page": 16,
"current_page": 1,
"last_page": 1627,
"next_page_url": "http://localhost:8000/items?page=2",
"prev_page_url": null,
"from": 1,
"to": 16,
"data": [
{
"id": 1,
...
},
{
"id": 2,
...
},
...
]
}
}
I successfully display items data in render method like this:
let items = _.map(this.state.items, (item) => {
return (
<div key={item.id}>
<div className="content">
<span>
{item.type}
</span>
...
</div>
</div>
)
});
and then return it like so:
return (
<div>
{items}
</div>
<div>
<a href={this.state.nextPage}>Next</a>
</div>
)
I can see that URL changes after I press Next button to page2 but there are two issues: I want to change items components based on JSON file when I click Next (i.e first page contains the first set of 16 elements, second page contains the second set) but there is no change and when I click Next button again but on the second page (according to URL) it doesn't get me to the third page and so on.
I know I need to somehow bind these state to page2 URL shows content described on the second page and I ran through tutorials but they seem to be outdated in case I use React 15.2.1.
I would appreciate any help or a thought that'd help me to solve it!
Add a click handler to your link element and pass the url as parameter. In the handler function make the ajax request and update the states using setState (similar to the one u did it on componentDidMount).
constructor() {
super();
this.state = {
items: [],
totalPages: '',
nextPage: ''
};
this._loadData = this._loadData.bind(this);
}
componentDidMount() {
const url = 'http://localhost:8000/items?json=true';
this._loadData(url);
}
_loadData(url) {
request.get(url).then((response) => {
this.setState({
items: response.body.items.data,
totalPages: response.body.items.last_page,
nextPage: response.body.items.next_page_url
});
});
}
render() {
let items = _.map(this.state.items, (item) => {
return (
<div key={item.id}>
<div className="content">
<span>
{item.type}
</span>
...
</div>
</div>
)
});
return (
<div>
{items}
</div>
<div>
<a href="#0" onClick={this._loadData(this.state.nextPage)}>Next</a>
</div>
)
}

"[object object]" shown when double-clicking input

Below is the template I am using for the directive. In code we are
fetching the data from a service in that data we have all the
information of that particular person. And from that data we are
showing only first name, last name and designtion or company
affiliation.
<div ng-if="model" class="entry-added">
<span class="form-control"><b>{{model.fullName}}</b>, <br/><span class="small-font">{{(model.designation)?model.designation:model.companyAffiliation}}</span></span>
<a ng-click="removePerson()" class="action-remove"><i class="fa fa-remove"></i></a>
</div>
<div ng-show="!model" class="input-group">
<input type="text"
class="form-control"
name="{{name}}"
id="{{name}}"
placeholder="{{placeholder}}"
ng-required="{{isRequired}}"
typeahead-on-select = "change($item, $model, $label)"
ng-model="model"
typeahead-min-length="3",
typeahead="suggestion for suggestion in searchEmployees($viewValue)"
typeahead-template-url="typeAheadTemplate.html"
typeahead-loading="searching"
typeahead-editable="false">
<script type="text/ng-template" id="typeAheadTemplate.html">
<a class="ui-corner-all dropdown" tabindex="-1">
<div class="col-md-2"><img class="dropdown-image" ng-src="https://people.***.com/Photos?empno={{match.model.employeeNumber}}"></div>
<div>
<div bind-html-unsafe="match.model.fullName"></div>
<div bind-html-unsafe="match.model.designation"></div>
</div>
</a>
</script>
I am using a custom directive to display a search field. The drop down is displaying [object object].
Directive
// In backend taxDeptContact is a Person type object
/*
Directive code
*/
(function () {
'use strict';
angular.module('treasuryApp.directives').directive('employeeSearch', employeeSearch);
employeeSearch.$inject = ['$resource', '$rootScope', 'ErrorHandler'];
function employeeSearch($resource, $rootScope, ErrorHandler) {
return {
restrict: 'E',
require: '^form',
scope: {
model: "=",
isRequired: '#',
submitted: "=",
onSelect: '&',
name: '#',
index:'#'
},
link: function(scope, el, attrs, formCtrl) {
//set required attribute for dynamically changing validations
scope.searchEmployees = function (searchTerm) {
var users = [];
var myResult = [];
var result = $resource($rootScope.REST_URL + "/user/getEmployees", {term: searchTerm}).query().$promise.then(function (value) {
//console.log(value)
$.each(value, function(i, o) {
users.push(o);
});
return users;
});
return result;
}
scope.removePerson = function() {
scope.model=null;
}
scope.userNotSelectedFromTypeahead = function(name) {
if(undefined === formCtrl[name]) {
return false;
}
return formCtrl[name].$error.editable;
};
scope.change = function(item, model, label) {
scope.model = item
scope.onSelect(
{name: scope.name, person: scope.model});
},
templateUrl: 'app/components/common/directives/employee-search.tpl.html'
};
}
})();
View that is using the directive
<div class="form-group">
<label class="col-sm-3>Tax Dept Contact</label>
<div class="col-sm-4">
<employee-search model="reqCtrl.requestObj.taxDepartmentContact" name="taxDeptContact" is-required="false" submitted="reqCtrl.submitted"/>
</div>
</div>
Image of the error occuring
Looks like this may be your trouble spot
typeahead="suggestion for suggestion in searchEmployees($viewValue)"
suggestion for suggestion is pulling the whole object. Have you tried displaying a particular attribute of suggestion?
For example: if you had a suggestion.name attribute you would write:
typeahead="suggestion.name for suggestion in searchEmployees($viewValue)"
Finally got the answer: I used autocomplete="off" in my directive and thats all
<input type="text" autocomplete="off" />

scope in directive does'nt work

I want to add input element to my Google Map.
I wrote the following code:
app.directive('GooglePlaceAutoComplete', function() {
return {
restrict:'AEC',
replace: true,
scope: {
myMap:'='
},
template: '<input id="google_places" name="google_places" type="text" class="input-block-level"></input>',
link: function($scope, elm , attr){
var input = document.getElementById('google_places');
var autocomplete = new google.maps.places.Autocomplete(input);
autocomplete.bindTo('bounds', $scope.myMap);
google.maps.event.addListener(autocomplete, 'place_changed', function() {
alert('changed');
});
}
};
});
When I inspect the element I see that $scope.myMap == Undefined
And therefore get the following error:
TypeError: Cannot read property 'gm_bindings_' of undefined
at kf (https://maps.gstatic.com/maps-api-v3/api/js/21/3/main.js:25:19)
at El.T.(anonymous function).bindTo (https://maps.gstatic.com/maps-api-v3/api/js/21/3/main.js:25:204)
at link (file:///Users/ortal/Desktop/Js%20Excersize%202/googlemapjs.js:28:22)
at file:///Users/ortal/Desktop/Js%20Excersize%202/angular.min.js:72:222
at $ (file:///Users/ortal/Desktop/Js%20Excersize%202/angular.min.js:72:278)
at N (file:///Users/ortal/Desktop/Js%20Excersize%202/angular.min.js:61:294)
at g (file:///Users/ortal/Desktop/Js%20Excersize%202/angular.min.js:54:244)
at N (file:///Users/ortal/Desktop/Js%20Excersize%202/angular.min.js:61:239)
at g (file:///Users/ortal/Desktop/Js%20Excersize%202/angular.min.js:54:244)
at file:///Users/ortal/Desktop/Js%20Excersize%202/angular.min.js:53:282
When I remove the following:
scope: {
myMap:'='
},
<div ng-app="app.ui-map" ng-controller="Controller">
<section id="map">
<div id="map_canvas" ui-map="myMap"
style="height:300px;width:400px;border:2px solid #777777;margin:3px; border:1px solid"
ui-options="mapOptions"
ui-event="{'map-idle' : 'onMapIdle()'}"
>
</div>
<div ng-repeat="marker in myMarkers" ui-map-marker="myMarkers[$index]"
ui-event="{'map-click': 'markerClicked(marker)'}"></div>
</section>
<div GooglePlaceAutoComplete></div>
I get no error but the nothing happend when the address is changed
Try adding
scope: true,
To your directive. Like this:
app.directive('GooglePlaceAutoComplete', function() {
return {
restrict:'AEC',
replace: true,
scope: true, <-------- HERE
scope: {
myMap:'='
},
...
...