I have a angularjs ng-click function that filters the results of a list based on the searchText when a tab is clicked. However, Why does the function show up in the text box when clicking on one of the tabs and how to I prevent that from showing up? Thank you. The entire code can be seen on at this codepen.
AngularJS generated tabs
<span class="tab-span" ng-repeat="tab in tabs" ng-click="updateTab(tab.value,$event.currentTarget)">{{tab.label}}</span>
updateTab function
$scope.tabs = [
{value: undefined, label: 'All', },
{value: 'Infrastructure', label: 'Infrastructure'},
{value: 'CSI', label: 'CSI'},
{value: 'EnterpriseSIEMContentCreate', label: 'Enterprise SIEM'}
];
$scope.updateTab = function(filterText,element) {
var spans = document.querySelectorAll(".tab-span");
spans.forEach(span => {
span.classList.remove("active-span");
});
element.classList.add("active-span");
if(!filterText){
$scope.searchText = filterText;
} else {
$scope.searchText = function(e) {
return (filterText.indexOf(e.AssignedTo) !== -1);
};
}
};
$scope.defaultSpanView = function() {
var sp = document.querySelectorAll(".tab-span");
console.log(sp);
};
$scope.defaultSpanView();
Related
Excuse any syntax errors, It works perfectly, but I could have made an error copying over.
Problem: I have a component, 'dropdown', that is repeated three times with
v-for='(item, index) in search'
which is an array with three objects. Below in the 'filterInput' method, The for loop and if statement does indeed work as intended, HOWEVER, I do not know how to target the 'dropdown' element that matches the search[i]. I need to remove the search[i]'s element in the DOM when the search[i].text doesn't match the input.
<div id='app'>
<input type='text' placeholder='Start typing here...' v-model='input'
#click='drop()' v-on:blur='close()'>
<ul id="dropdown" class='nodisplay'>
<dropdown v-for='(item, index) in search' v-bind:item='item' v-
bind:index='index'></dropdown>
</ul>
</div>
Vue.component('dropdown', {
props: ['item', 'index'],
template: `<li> {{item.text}}</li>`
})
var app = new Vue({
el: '#app',
data: {
input: '', //reactive
search: [
{id: 1, text: 'Jacob'},
{id: 2, text: 'Jeff'},
{id: 3, text: 'Tom'}
]
},
methods: {
drop: function() {
let dropdown = document.getElementById('dropdown');
dropdown.classList.toggle('nodisplay');
},
close: function() {
let dropdown = document.getElementById('dropdown');
dropdown.classList.toggle('nodisplay');
document.querySelector('input').value = '';
},
filterInput: function(index) {
//dropdown items in console: app.search[index].text = 'xyz'
for (let i = 0; i < this.search.length; i++) {
if (!(this.search[i].text.startsWith(this.input))) {
//hide or remove this current search element from dropdown
}
}
}
},
watch: {
input: function() {
this.filterInput();
}
}
})
tl;dr; how do I target
What you are looking for is how to have parent child communication, which I have answered today itself here.
You need to $emit an event from the child component and set the value used in input field, just like the example in documentation.
Here is the code:
HTML
<div id='app'>
<input type='text' placeholder='Start typing here...' v-model='input'
#click='drop()' >
<ul id="dropdown" :class="{'nodisplay': dropDownClosed}">
<dropdown v-for='(item, index) in search' v-bind:item='item' v-
bind:index='index' v-on:getdropdowninput="getdropdowninput"></dropdown>
</ul>
</div>
JS
dropdown = Vue.component('dropdown', {
props: ['item', 'index'],
template: `<div><li ><a #click="selectval(item.text)" href="#"> {{item.text}}</a></li></div>`,
methods: {
selectval (value) {
this.$emit("getdropdowninput", value)
}
}
})
var app = new Vue({
el: '#app',
data: {
input: '', //reactive
dropDownClosed: false,
search: [
{id: 1, text: 'Jacob'},
{id: 2, text: 'Jeff'},
{id: 3, text: 'Tom'}
]
},
methods: {
drop: function() {
this.dropDownClosed = true
},
getdropdowninput: function(value) {
this.dropDownClosed = false
this.input = value;
},
filterInput: function(index) {
//dropdown items in console: app.search[index].text = 'xyz'
for (let i = 0; i < this.search.length; i++) {
if (!(this.search[i].text.startsWith(this.input))) {
//hide or remove this current search element from dropdown
}
}
}
},
watch: {
input: function() {
this.filterInput();
}
}
})
Here is the working fiddle.
Use dynamic classes: I have also modified how to add/remove a class dynamically in vue way, instead of document.getElementById. Notice in following line:
<ul id="dropdown" :class="{'nodisplay': dropDownClosed}">
nodisplay class will be applied when dropDownClosed variable will be true and it will be removed when dropDownClosed variable will be false.
How to Filter:
To filter, you can use a computed property in the v-for and whenever input changes you can filter the search array, like following
computed: {
filteredInput: function(){
if(this.input === '' || !this.input){
return this.search
} else {
var self = this
return this.search.filter(
function( s ) {
return s.text.indexOf( self.input ) !== -1; }
);
}
}
See working fiddle here.
I building a sortable table in Meteor with Reactive-Table and having trouble getting my delete button to work for removing entries from the table.
Please see my javascript code below:
Movies = new Meteor.Collection("movies");
if (Meteor.isClient) {
Template.body.events({
"submit .new-movie": function (event) {
var title = event.target.title.value;
var year = event.target.year.value;
var genre = event.target.genre.value;
Movies.insert({
title: title,
year: year,
genre: genre
});
event.target.title.value = "";
event.target.year.value = "";
event.target.genre.value = "0";
return false;
}
});
Template.moviestable.events({
"click .deletebtn": function (event) {
Movies.remove(this._id);
}
});
Template.moviestable.helpers({
movies : function () {
return Movies.find();
},
tableSettings : function () {
return {
showFilter: false,
fields: [
{ key: 'title', label: 'Movie Title' },
{ key: 'year', label: 'Release Year' },
{ key: 'genre', label: 'Genre' },
{ key: 'edit', label: 'Edit', fn: function () { return new Spacebars.SafeString('<button type="button" class="editbtn">Edit</button>') } },
{ key: 'delete', label: 'Delete', fn: function () { return new Spacebars.SafeString('<button type="button" class="deletebtn">Delete</button>') } }
]
}
}
});
}
Can anyone tell me what I'm doing wrong?
In the reactive tables docs, there's an example of how to delete rows from the table. Adapting the example in the docs for your needs, your event should look like this:
Template.moviestable.events({
'click .reactive-table tbody tr': function (event) {
event.preventDefault();
var objToDelete = this;
// checks if the actual clicked element has the class `deletebtn `
if (event.target.className == "deletebtn") {
Movies.remove(objToDelete._id)
}
}
});
The problem you are having is that you are trying to find the _id property on the button click instead of the row click.
If you do console.log(this) on your button click event (as you have it in your question above) you will get something like this Object {key: "delete", label: "", fieldId: "2", sortOrder: ReactiveVar, sortDirection: ReactiveVar} which does not contain the property _id
It is easier to register the row click, where the row object is the actual document you are trying to delete, and then check if the event's target has the delete class you added.
I need a filter with an "Apply" button and without autocomplete. I can't do that. Here's my basic code, with autocomplete (I don't want it) and without button (I want this).
I'm using Jade.
search.jade
input(type="text", ng-model="buscador.id", placeholder="Ejemplo: 111")
listmagazines.jade
.col-xlg-25.col-sm-3.col-xs-3.col-xxs-6(ng-repeat="magazine in magazines|filter:buscador")
app.js It has a lot of items, I'll put just three.
var app = angular.module("appBuscador", []);
app.factory("revistas", function(){
return{
"revistasNumeros":[
{
id: 97,
titulo: "Nº97",
img: "pdf97.jpg",
descarga: "",
url: "http://www.mapfre.com/fundacion/html/revistas/gerencia/n097/index.html"
},
{
id: 98,
titulo: "Nº98",
img: "pdf98.jpg",
descarga: "",
url: "http://www.mapfre.com/fundacion/html/revistas/gerencia/n098/index.html"
},
{
id: 99,
titulo: "Nº99",
img: "pdfdefault.jpg",
descarga: "",
url: "http://www.mapfre.com/fundacion/html/revistas/gerencia/n099/index.html"
}
]
}
})
controller.js
app.controller("revistasController", function($scope,revistas){
$scope.magazines = revistas.revistasNumeros;
})
Thank you.
--------------------- SORRY I CAN'T ADD AN ANSWER I'M BANNED
I found the solution:
search.jade (add a button)
input(type="text", ng-model="buscador.id", placeholder="Ejemplo: 111")
a.btn.btn-buscador(href="#", ng-click="applySearchFilter()") Buscar
listmagazines.jade (quit filter: and add the ng-hide)
.col-xlg-25.col-sm-3.col-xs-3.col-xxs-6(ng-repeat="magazine in magazines", ng-hide="magazine.excludedByFilter")
controller.js (add this to your app.controller and change the properties)
app.controller("revistasController", function($scope,revistas){
$scope.magazines = revistas.revistasNumeros;
$scope.applySearchFilter = function() {
var idFilter = $scope.buscador.id;
console.log(idFilter);
var showAll = 0 === idFilter.length;
angular.forEach($scope.magazines, function(magazine) {
var id = magazine.id.toString();
if (showAll) {
magazine.excludedByFilter = false;
} else {
magazine.excludedByFilter = (id.indexOf(idFilter) === -1)
|| (id.indexOf(idFilter) === -1);
}
});
}
})
It works!! :)
Using AngularJS I want to show and hide the data related with particular id in the toggle way.
My JSON Data format is like:
$scope.things = [{
id: 1,
data: 'One',
shown: true
}, {
id: 2,
data: 'Two',
shown: false
}, {
id: 3,
data: 'Three',
shown: true
}, ];
What I want is when click on id-1 It will show text One and Hide the others, when click on id-2 will show text Two and hide others and so on.
Here is the fiddle what I tried : jsfiddle : Demo Link
i updated your code
$scope.flipMode = function (id) {
$scope.things.forEach(function (thing) {
if(id == thing.id){
thing.shown = true;
}
else{
thing.shown = false;
}
})
};
{{thing.id}}
here is the working fiddle
It should work
$scope.flipMode = function (id) {
$scope.things.forEach(function (thing) {
if(thing.id === id) {
thing.shown = true;
return;
}
thing.shown = false;
})
};
<div ng-repeat="thing in things">
{{thing.id}}
</div>
Forked working solution: http://jsfiddle.net/nypmmkrh/
Change your scope function:
$scope.flipMode = function (id) {
$scope.things.forEach(function(thing) {
if(thing.id == id) {
thing.shown = true;
} else {
thing.shown = false;
}
});
};
And pass the id in the view:
{{thing.id}}
I have an app and everything is rendered fine. However, I can't catch the mainTabChanged Event and do not no why. I did everything like in the example, console logs FIRED, but never RECEIVED.
Why?
Ext.define('MyApp.controller.Tab', {
extend:'Ext.app.Controller',
init:function () {
var me = this;
me.mainWindow = me.getView('tab.List').create();
me.control({
'mainTab': {
mainTabChanged: me.onMainTabChanged
}
});
},
me.onMainTabChanged: function(oldTab, newTab, settings) {
console.log("received");
console.log(settings);
}
});
Ext.define('MyApp.view.tab.List', {
extend:'Ext.form.FieldSet',
alias:'widget.mainTab',
initComponent:function () {
var me = this;
me.title = 'App'
me.items = me.createElements();
me.addEvents(
'mainTabChanged'
);
me.callParent(arguments);
},
createElements: function () {
var me = this, tabs = [];
tabs = [{
title: 'Tab 1',
bodyPadding: 10,
html : 'A simple tab'
},
{
title: 'Tab 2',
html : 'Another one'
}];
var tabPanel = Ext.create('Ext.tab.Panel', {
height: 150,
activeTab: 0,
plain: true,
items : tabs,
listeners: {
beforetabchange: function(panel, newTab, oldTab) {
console.log("FIRED");
me.fireEvent('mainTabChanged', oldTab, newTab, 'Test');
}
}
});
return tabPanel;
}
});
I think the problem is that your widget "mainTab" is a 'List', but you are firing the event from a 'tabpanel'.
In the controller try this:
me.control({
'mainTab > tabpanel': {
mainTabChanged: me.onMainTabChanged
}
or just
me.control({
'tabpanel': {
mainTabChanged: me.onMainTabChanged
}
My problem was, that I was trying to injecting one app into another. I have now solved the problem by not injecting the app, but by injecting the controller and views directly into the app and hence make them a native part of the app, so they will not bypass the event bus.