I have two lists , user can drag items from list 1 to list 2 and there is a button with text input so user can add his own input to the list 2 which will be automatically updated in my MYSQL database using axios.
This is AddItem script
addItembh(){
var input = document.getElementById('itemFormbh');
if(input.value !== ''){
// this line makes a new article with input value but no attribute :(
this.tasksNotCompletedNew.unshift({
behv_skilldesc:input.value
});
axios.post('../joborder/addAttrib', {
behv_skilldesc: input.value,
type:'behvnew',
joborder_id: this.joborder_id ,
alljobs_id: this.alljobs_id
}).then((response) => {
console.log(response.data);
}).catch((error) => {
console.log(error);
});
input.value='';
}
},
To be clear on the question : I need to assign an attribute to my new article thats getting created so I can find the text of that attrib later on deleteItem method
UPDATE :
<template>
<div class="row">
<div class="col-md-4 col-md-offset-2">
<section class="list">
<header>Drag or Add Row Here</header>
<draggable class="drag-area" :list="tasksNotCompletedNew" :options="{animation:200, group:'status',handle:'disabled'}" :element="'article'" #add="onAdd($event, false)" #change="update">
<article class="card" v-for="(task, index) in tasksNotCompletedNew" :key="task.prof_id" :data-id="task.prof_id" #change="onChange">
<span >
{{ task.prof_skilldesc }}
</span>
<span v-if="task.prof_skilldesc !== 'Drag Here'">
<button class="pull-left" #click="deleteItem(task.prof_id) + spliceit(index)" ><i class="fa fa-times inline"></i></button>
</span>
</article>
<article class="card" v-if="tasksNotCompletedNew == ''">
<span>
Drag Here
</span>
</article>
</draggable>
<div>
<input id='itemForm' />
<button v-on:click='addItem' class="btn btn-theme btn-success" style='margin-top:5px;' >Add a row </button>
</div>
</section>
</div>
<div class="col-md-4">
<section class="list">
<header>List of Skills ( Hold left click )</header>
<draggable class="drag-area" :list="tasksCompletedNew" :options="{animation:200, group:'status'}" :element="'article'" #add="onAdd($event, true)" #change="update">
<article class="card"
v-for="(task, index) in visibleskills"
:key="task.prof_id" :data-id="task.prof_id"
>
{{ task.prof_skilldesc }}
<div v-if="index == 4" style="display:none" >{{index2 = onChange(index)}}</div>
</article>
<pagination
v-bind:tasksCompletedNew ="tasksCompletedNew"
v-on:page:update ="updatePage"
v-bind:currentPage ="currentPage"
v-bind:pageSize="pageSize">
</pagination>
</draggable>
</section>
</div>
</div>
</template>
So on Add a row our method will be called .
Thanks for any help
Related
I've got a pretty straight forward setup.
Trying to display a list of users with a search box at the top (for actively filtering the search results).
If I use just that the page works and displays fine.
I'm trying to add in an additional dropdown to pick an attribute to sort by (and hopefully add in another dropdown to indicate ascending/descending once I get the first dropdown working).
My current code (with a non-working version of the sort) looks like this:
<div id="app">
<section class="mb-3">
<div class="container">
<h2>Person Search</h2>
<h3>
<small class="text-muted">Filter people based on the name, location or job</small>
</h3>
<h3>
<small class="text-muted">
Examples: “Jane Doe”, “ABC Building”, or “Math”
</small>
</h3>
<input type="text" class="form-control" v-model="search_term" placeholder="Begin typing to filter by name, location or job...">
<!-- THIS WOULD CAUSE THE LIST TO FILTER ALPHABETICALLY BY SELECTED ATTRIBUTE -->
<select id="sortFilterSelect" name="sort_filter" v-model="sort_filter">
<option value="">Sort By...</option>
<option value="first_name">First Name</option>
<option value="last_name">Last Name</option>
</select>
</div>
</section>
<section>
<div class="container">
<h3>People List : ([[ people_count ]] People)</h3>
<!-- I ADDED 'sortedPeople' HERE - WHICH BROKE IT -->
<div v-for="person in filteredPeople | sortedPeople">
<div class="card mb-4" :class="person.has_summative_past_due ? 'alert-warning' : ''">
<div class="card-body row" >
<div class="col">
<h4 class="card-title" v-bind:person='person.full_name'><a v-bind:href="'{% url 'commonground:index' %}' + 'users/' + person.id">[[ person.full_name ]]</a></h4>
<p v-if="person.active_summative" class="card-text">
Active Summative Due Date: [[ person.active_summative.due_date ]]
<span v-show="!person.active_summative.past_due" v-bind:past_due='person.active_summative.past_due' class="badge badge-success">[[ person.active_summative.due_date_status ]]</span>
<span v-show="person.active_summative.past_due" class="badge badge-danger">[[ person.active_summative.due_date_status ]]</span>
<ul class="list-group list-group-flush">
<li class="list-group-item justify-content-between align-items-center" v-for="summary in person.summative_evaluations_summary">
<span class="badge badge-secondary badge-pill">[[summary.evaluation_type__count]]</span> [[ summary.evaluation_type__name ]]
</li>
</ul>
</p>
<p v-if="!person.active_summative" class="card-text">
No Active Unlocked Summatives
</p>
<a v-if="person.active_summative" :href="person.active_summative.absolute_url" class="btn btn-primary"><i class="far fa-edit"></i> View / Edit Active Summative</a>
</div>
<div class="col-auto float-right text-right">
<p class="h5">
[[ person.base_location ]]
<div v-if="person.multiple_locations" class="small text-muted"><i class="fal fa-info-circle"></i> User has multiple locations</div>
</p>
<p class="h5">
[[ person.assignment_job ]]
<div v-if="person.multiple_jobs" class="small text-muted"> <i class="fal fa-info-circle"></i> User has multiple jobs</div>
</p>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- END OF VUE -->
</div>
The actual Vue code looks like this:
<script>
const app = new Vue({
delimiters: ['[[', ']]'],
el: '#app',
data: {
people: [],
people_count: 0,
search_term: "",
sort_filter: "",
},
computed: {
filteredPeople:function()
{
var search = this.search_term.toLowerCase();
return this.people.filter(function(person){
return Object.values(person).some( val => String(val).toLowerCase().includes(search))
})
},
sortedPeople:function()
{
var sort_filter = this.sort_filter.toLowerCase();
console.log('triggered')
return this.people.filter(function(person){
return Object.values(person).some( val => String(val).toLowerCase().includes(sort_filter))
})
},
},
async created () {
var response = await fetch("{% url 'user-list' %}");
this.people = await response.json();
this.people_count = await this.people.length
}
})
</script>
Fairly new to Vue, but I am building this to learn. All help is appreciated!
Check out the simple sample I made: Link
filteredPeople() {
return this.people.filter(
(person) =>
person.firstname
.toLowerCase()
.includes(this.search.toLowerCase().trim()) ||
person.lastname
.toLowerCase()
.includes(this.search.toLowerCase().trim())
);
},
sortedPeople() {
return this.filteredPeople.sort((a, b) =>
a[this.sortby].localeCompare(b[this.sortby])
);
},
Added asc/dec order: Link
sortedPeople() {
return this.filteredPeople.sort((a, b) =>
(this.sort == 'asc') ? a[this.sortby].localeCompare(b[this.sortby]) : b[this.sortby].localeCompare(a[this.sortby])
);
},
What I need to do is to display the filtered array in the DOM once I click on any value from the dropdown. The return from filtered function is right but I couldn't update the DOM.
HTML CODE
This is my side dropdown list that I take the value from
<div class="col-md-3">
<div class="widget">
<h4 class="widget-title">Sort By</h4>
<div>
<select class="form-control" (change)="selectChangeHandler($event)">
<option value="Man">Man</option>
<option value="Women">Women</option>
<option value="Accessories">Accessories</option>
<option value="Shoes">Shoes</option>
</select>
</div>
</div>
</div>
Table that shows the results on DOM take the value from above dropdown list to be able to show them by category. Unfortunately the DOM doesn't change (I used NGX pagination library), please see my TS code that sends the filtered array to the loop? So, I don't understand why it didn't update.
<div class="col-md-9">
<div class="row" id="top">
<div class="col-md-4" *ngFor="let item of collection | paginate: { itemsPerPage: 100, currentPage: p ,id: 'foo' }">
<div class="product-item">
<div class="product-thumb">
<span class="bage">Sale</span>
<img class="img-responsive" src="https://via.placeholder.com/150" alt="product-img" />
<div class="preview-meta">
<ul>
<li>
<span data-toggle="modal" data-target="#product-modal">
<i class="fas fa-search"></i>
</span>
</li>
<li>
</i>
</li>
<li>
<i class="fas fa-shopping-cart"></i>
</li>
</ul>
</div>
</div>
<div class="product-content">
<h4>{{item.name}}</h4>
<p class="price">{{item.price}}</p>
</div>
</div>
</div>
Type Script Code
export class AllproductsComponent implements OnInit {
allProducts:any[]=[]
filteredData=[...this.allProducts]
p: number = 1;
collection: any[] = this.filteredData;
constructor(private _allproducts:ProductService) {
console.log(this.collection);
}
ngOnInit(): void {
this.getAllProducts()
}
getAllProducts():any{
this._allproducts.getAllproducts().subscribe(res=>{
console.log(res.data);
this.allProducts = res.data
this.collection =res.data
})
}
pageChanged(pee:number){
document.getElementById("top").scrollIntoView()
}
selectChangeHandler(value:any){
console.log(value.target.value);
console.log(this.filteredData);
this.filteredData = this.allProducts.filter(key=>{
if(value.target.value === "Man"){
if(key.price > 20)return this.allProducts
}else if(value.target.value === "Women"){
if(key.price < 20) return this.allProducts
}else {
return this.allProducts
}
})
console.log(this.filteredData);
}
}
I appreciate your help, thanks a lot.
allProducts:any[]=[]
filteredData=[...this.allProducts]
collection: any[] = this.filteredData;
you are initializing data before it is called from your api , so it's normal it will never work. You have to reinitialize it inside your method
this._allproducts.getAllproducts().subscribe(res=>{ ..});
I have this problem:
I render a list obtained by an API call with a v-for, and if you write into a form, only the elements that match the key written into the form are showed
Now, I need to sort this elements by name and by price too using a dropdown with buttons
is it possible?
Sorry for the external link, but I have some trouble pasting code into StackOverflow, maybe due the vue-boostrap
HTML part
code part
<div>
<b-dropdown id="dropdown-1" text="Dropdown Button" class="m-md-2">
<b-dropdown-item>Default Sort</b-dropdown-item>
<b-dropdown-divider></b-dropdown-divider>
<b-dropdown-item #click="sortByName">Sort by Name</b-dropdown-item>
<b-dropdown-divider></b-dropdown-divider>
<b-dropdown-item>Sot by Price</b-dropdown-item>
</b-dropdown>
</div>
<div class="d-flex flex-wrap justify-content-center">
<div class="card" v-for="product in filteredCatalogue" :key="product.id">
<img class="product pimage" :src="product.images.small" />
<hr class="product black-line" />
<h5 class="product name text-uppercase">{{product.name}}</h5>
<h5 class="product short-description">{{product.descriptions.short}}</h5>
<h5
class="product price"
v-if="product.price.currency_symbol=='€'"
>€ {{product.price.sell}}</h5>
<b-button id="button-shop" squared variant="warning">
<i class="fas fa-shopping-cart"></i>
<div id="yellow-button-text">ADD TO CART</div>
</b-button>
</div>
</div>
<form class="form-inline justify-content-center">
<div class="form-group">
<input
class="form-control bg-white border border-secondary"
type="text"
v-model="key"
placeholder="Cerca tra i prodotti"
value
autocomplete="off"
/>
</div>
</form>
import axios from "axios";
import { cacheAdapterEnhancer } from "axios-extensions";
export default {
data() {
return {
catalogue: [],
key: ""
};
},
created() {
axios
.get(
API_URL,
cacheAdapterEnhancer
)
.then(response => {
this.catalogue = response.data;
console.log(this.catalogue);
})
.catch(error => console.log(error));
},
computed: {
filteredCatalogue: function() {
return this.catalogue.filter(product => {
return product.name.toLowerCase().match(this.key.toLowerCase());
});
}
}
};
Check sort method on JavaScrtipt array here.
I am new to Vue and am using the Bootstrap modals to display product information. I have grid containers that each have a product picture, description, and two buttons. One of the buttons(More details >>), when clicked, would shoot a modal window that should show the very same product description and picture of the grid it was contained in.
<div id="myapp">
<h1> {{ allRecords() }} </h1>
<div class="wrapper" >
<div class="grid-container" v-for="product in products" v-bind:key="product.ID">
<div class="Area-1">
<img class="product_image" src="https:....single_product.jpg">
</div>
<div class="Area-2">
<div class = "amount">
{{ product.amount }}
</div>
{{ product.Description }}
</div>
<div class="Area-3">
<b-button size="sm" v-b-modal="'myModal'" product_item = "'product'">
More Details >>
</b-button>
<b-modal id="myModal" >
<h1> {{ product.Name }} </h1>
<h3> {{ product.Description }} </h3>
</b-modal>
</div>
<div class="Area-4">
<br><button>Buy</button>
</div>
</div>
</div>
</div>
var app = new Vue({
'el': '#myapp',
data: {
products: "",
productID: 0
},
methods: {
allRecords: function(){
axios.get('ajaxfile.php')
.then(function (response) {
app.products = response.data;
})
.catch(function (error) {
console.log(error);
});
},
}
})
Area 1, 2 and 4 work perfectly fine and they display the product data according to the v-for value and as expected respectively for each grid container. Area 3 is a problem here when I click the More details >> button, I just see a faded black screen. I am not sure what I am doing wrong here, would really appreciate some help.
Add a property selectedProduct, then on More Details button click event, assign the current product to the selectedProduct member as below :
HTML
<div class="Area-3">
<b-button size="sm" v-b-modal="'myModal'"
#click="selectProduct(product)">More Details >> </b-button>
<b-modal id="myModal">
<h1> {{ this.selectedProduct.Name }} </h1>
<h3> {{ this.selectedProduct.Description }} </h3>
</b-modal>
</div>
Javascript:
var app = new Vue({
'el': '#myapp',
data: {
products: "",
productID: 0,
selectedProduct: {Name: '', Description: '', Amount:0}
},
methods: {
allRecords: function(){
...
},
selectProduct: function(product)
{
this.selectedProduct = product;
}
...
}
I can't replicate the issue. I created JSFiddle to test:
https://jsfiddle.net/4289wh0e/1/
However, I realized multiple modal elements are displayed when I click on the "More Details" button.
I suggest you add only one modal in the wrapper and store the chosen product in a data variable.
https://jsfiddle.net/4289wh0e/2/
<div id="myapp">
<h1> {{ allRecords() }} </h1>
<div class="wrapper">
<div class="grid-container" v-for="product in products" v-bind:key="product.ID">
<div class="Area-1"><img class="product_image" src="https:....single_product.jpg"> </div>
<div class="Area-2">
<div class="amount">{{ product.amount }} </div>
{{ product.Description }}</div>
<div class="Area-3">
<b-button size="sm" v-b-modal="'productModal'" #click="chooseProduct(product)" product_item="'product'">More Details >> </b-button>
</div>
<div class="Area-4">
<br>
<button>Buy</button>
</div>
</div>
<b-modal id="productModal" v-if="chosenProduct">
<h1> {{ chosenProduct.Name }} </h1>
<h3> {{ chosenProduct.Description }} </h3>
</b-modal>
</div>
</div>
Vue.use(BootstrapVue)
var app = new Vue({
'el': '#myapp',
data: {
products: [],
chosenProduct: null
},
methods: {
chooseProduct: function (product) {
this.chosenProduct = product
},
allRecords: function(){
this.products = [
{
ID: 1,
Description: 'dek',
Name: 'Name',
amount: 100
},
{
ID: 2,
Description: 'dek 2',
Name: 'Name 2',
amount: 300
}
]
},
}
})
The reason you're just seeing a black screen is because you're not giving the b-modal in your v-for a unique ID.
So when you click the button it's actually opening all the modals at the same time, and stacking the backdrop making it look very dark.
Instead you could use your product ID (I'm guessing it's unique) in your modal ID to make it unique
<div id="myapp">
<h1> {{ allRecords() }} </h1>
<div class="wrapper" >
<div class="grid-container" v-for="product in products" v-bind:key="product.ID">
<div class="Area-1">
<img class="product_image" src="https:....single_product.jpg">
</div>
<div class="Area-2"><div class = "amount">{{ product.amount }} </div>
{{ product.Description }}
</div>
<div class="Area-3">
<b-button size="sm" v-b-modal="`myModal-${product.ID}`" product_item = "'product'">
More Details >>
</b-button>
<b-modal :id="`myModal-${product.ID}`" >
<h1> {{ product.Name }} </h1>
<h3> {{ product.Description }} </h3>
</b-modal>
</div>
<div class="Area-4">
<br><button>Buy</button>
</div>
</div>
</div>
</div>
Example pen:
https://codepen.io/Hiws/pen/qBWJjOZ?editors=1010
I am very new to the smart table. I have gone through its documentation on Smart Table.
But the I haven't found how to bind data on click event in smart table?
Code is very big but I am trying to post it here.
<div class="table-scroll-x" st-table="backlinksData" st-safe-src="backlinks" st-set-filter="myStrictFilter">
<div class="crawlhealthshowcontent">
<div class="crawlhealthshowcontent-right">
<input type="text" class="crserachinput" placeholder="My URL" st-search="{{TargetUrl}}" />
<a class="bluebtn">Search</a>
</div>
<div class="clearfix"></div>
</div>
<br />
<div class="table-header clearfix">
<div class="row">
<div class="col-sm-6_5">
<div st-sort="SourceUrl" st-skip-natural="true">
Page URL
</div>
</div>
<div class="col-sm-2">
<div st-sort="SourceAnchor" st-skip-natural="true">
Anchor Text
</div>
</div>
<div class="col-sm-1">
<div st-sort="ExternalLinksCount" st-skip-natural="true">
External<br />Links
</div>
</div>
<div class="col-sm-1">
<div st-sort="InternalLinksCount" st-skip-natural="true">
Internal<br />Links
</div>
</div>
<div class="col-sm-1">
<div st-sort="IsFollow" st-skip-natural="true">
Type
</div>
</div>
</div>
</div>
<div class="table-body clearfix">
<div class="row" ng-repeat="backlink in backlinksData" ng-if="backlinks.length > 0">
<div class="col-sm-6_5">
<div class="pos-rel">
<span class="display-inline wrapWord" tool-tip="{{ backlink.SourceUrl }}"><b>Backlink source:</b> <a target="_blank" href="{{backlink.SourceUrl}}">{{ backlink.SourceUrl }}</a></span><br />
<span class="display-inline wrapWord" tool-tip="{{ backlink.SourceTitle }}"><b>Link description:</b> {{ backlink.SourceTitle }}</span> <br />
<span class="display-inline wrapWord" tool-tip="{{ backlink.TargetUrl }}"><b>My URL:</b> <a target="_blank" href="{{backlink.TargetUrl}}">{{ backlink.TargetUrl }}</a></span><br />
</div>
</div>
<div class="col-sm-2">
<div class="pos-rel">
{{ backlink.SourceAnchor }}
</div>
</div>
<div class="col-sm-1">
<div>
{{ backlink.ExternalLinksCount }}
</div>
</div>
<div class="col-sm-1">
<div>
{{ backlink.InternalLinksCount }}
</div>
</div>
<div class="col-sm-1">
<div ng-if="!backlink.IsFollow">
No Follow
</div>
</div>
</div>
<div class="row" ng-if="backlinks.length == 0">
No backlinks exists for selected location.
</div>
</div>
<div class="pos-rel" st-pagination="" st-displayed-pages="10" st-template="Home/PaginationCustom"></div>
</div>
and my js code is here.
module.controller('backlinksController', [
'$scope','$filter', 'mcatSharedDataService', 'globalVariables', 'backlinksService',
function ($scope,$filter, mcatSharedDataService, globalVariables, backlinksService) {
$scope.dataExistsValues = globalVariables.dataExistsValues;
var initialize = function () {
$scope.backlinks = undefined;
$scope.sortOrderAsc = true;
$scope.sortColumnIndex = 0;
};
initialize();
$scope.itemsByPage = 5;
var updateTableStartPage = function () {
// clear table before loading
$scope.backlinks = [];
// end clear table before loading
updateTableData();
};
var updateTableData = function () {
var property = mcatSharedDataService.PropertyDetails();
if (property == undefined || property.Primary == null || property.Primary == undefined || property.Primary.PropertyId <= 0) {
return;
}
var params = {
PropertyId: property.Primary.PropertyId
};
var backLinksDataPromise = backlinksService.getBackLinksData($scope, params);
$scope.Loading = backLinksDataPromise;
};
mcatSharedDataService.subscribeCustomerLocationsChanged($scope, updateTableStartPage);
}
]);
module.filter('myStrictFilter', function ($filter) {
return function (input, predicate) {
return $filter('filter')(input, predicate, true);
}
});
But It is working fine with the direct search on textbox.
but according to the requirement I have to perform it on button click.
Your suggestions and help would be appreciated.
Thanks in advance.
You can search for a specific row by making some simple tweaks.
add a filter to the ng-repeat, and filter it by a model that you will insert on the button click, like so: <tr ng-repeat="row in rowCollection | filter: searchQuery">
in your view, add that model (using ng-model) to an input tag and define it in your controller
then pass the value to the filter when you click the search button
here's a plunk that demonstrates this
you can use filter:searchQuery:true for strict search
EDIT:
OK, so OP's big problem was that the filtered values wouldn't show properly when paginated, the filter query is taken from an input box rather then using the de-facto st-search plug-in, So I referred to an already existing issue in github (similar), I've pulled out this plunk and modified it slightly to fit the questioned use case.