اذهب إلى المحتوى

السؤال

نشر

السلام عليكم ورحمة الله وبركاته.

اقوم بإنشاء برنامج للفواتير. في صفحة تعديل الفاتورة عندي select للقسم - بها جميع الاقسام الموجودة بالموقع ويتم عمل auto select للoption المدخل في الفاتورة مسبقا يعني اذا كانت منتج الفاتورة يساوي test فعند تعديل الفاتورة سيكون option test داخل الselect له selected' atribute ' - و select اخري بها المنتجات هكذا

<div class="row">
  <div class="col-lg-4 col-sm-6 col-12 mb-3 mb-sm-0">
    <div class="mb-3">
      <label for="section">القسم</label>
      <select name="section" class="form-control 
                                    @error('section')
                                    is-invalid
                                    @enderror" id="section">
        <option value="NULL" disabled>إختر القسم</option>
        @foreach($sections as $section)
        <option value="{{ $section->id }}" @if($section->id == $invoice->section)
          selected
          @endif
          >
          {{ $section->name }}
        </option>
        @endforeach
      </select>
      @error('section')
      <small class="invalid-feedback">{{ $message }}</small>
      @enderror
    </div>
  </div>
  <div class="col-lg-4 col-sm-6 col-12 mb-3 mb-sm-0">
    <div class="mb-3">
      <label for="product">المنتج</label>
      <select name="product" class="form-control 
                                    @error('product')
                                    is-invalid
                                    @enderror" id="product">
        <option value="NULL" disabled selected>إختر المنتج</option>
      </select>
      @error('product')
      <small class="invalid-feedback">{{ $message }}</small>
      @enderror
    </div>
  </div>
</div>

وقمت بكتابة هذه الفانكشن بأجاكس لجلب المنتجات التي لها id يساوي id القسم الذي تم إختياره.

function getProducts(target) {
  let getProducts = new XMLHttpRequest();
  getProducts.open('GET', '/invoices/getProducts/' + target);

  getProducts.onload = function() {
    if (this.readyState === 4 && this.status === 200) { // succes
      let products = JSON.parse(this.responseText);
      products.forEach(function(item) {
        let option = document.createElement('option'),
            text = document.createTextNode(item['product_name']);
        option.appendChild(text);
        option.value = item['id'];
        productsSelect.appendChild(option);
      });
    } else {
      alert('لقد حدث خطأ غير متوقع');
    }
  }

  getProducts.send();
}

فكما ترون في الفانكشن قمت بعمل عناصر جديدة بإتسخدام جافاسكربت عن طريق دالة appendChild() وقمت بإضافتها في select الخاصة بالمنتجات

عندما اريد تنفيذ حدث معين على الoptions المضافة لا يمكن بسبب ان هذه العناصر غير مقروئة في الجافا سكربت.. اعني انها تكون مقروئة بشكل عادي جدا في الpage source ولكن عندما اقوم بكتابة 

console.log(document.querySelectorAll('select#products option'));

تكون النتيجة فارغة بسبب ان العناصر تم إنشائها وليست عناصر اساسية فهل من حل؟ 

استعمل laravel ولكن اظن ان سؤالي متعلق بالجافاسكربت وشكراً

Recommended Posts

  • 0
نشر
بتاريخ 35 دقائق مضت قال يوسف احمد9:

الفكرة أخي الكريم أن الأوبشن الجديدة لن يتم الإستماع إليها لأن ال DOM تم تحميلها بالفعل ولذلك يجب علينا أن نجعل الجافا إسكربت تقوم بالإستماع لأي شئ جديد عن طريق أكتر من حل :


$(document).delegate('#section', 'change', function (e) {
    // write your code here
});

أو عن طريق دالة ال on


$(document).on('change', '#section', function() {
   // write your code here
});

 

للاسف اخي لم تعمل شكرا لك

للاسف لم اعرف حلاً للمشكلة ولكن فكرت في حل اخر ونجح بفضل الله

وهو في الفانكشن المستخدمة

function getProducts(target) {
  let getProducts = new XMLHttpRequest();
  getProducts.open('GET', '/invoices/getProducts/' + target);

  getProducts.onload = function() {
    if (this.readyState === 4 && this.status === 200) { // succes
      let products = JSON.parse(this.responseText);
      products.forEach(function(item) {
        let option = document.createElement('option'),
            text = document.createTextNode(item['product_name']);
        option.appendChild(text);
        option.value = item['id'];
        productsSelect.appendChild(option);
      });
    } else {
      alert('لقد حدث خطأ غير متوقع');
    }
  }

  getProducts.send();
}

وجدت انها تنجح عندما أقوم بكتابة العمليات التي اريدها على الoptions بداخل ميثود الforEach نفسها اي قبل تضمينها في الdom tree وشكرا

  • 0
نشر

يبدوا أن المشكلة في تحديد العناصر فقط :

بتاريخ منذ ساعة مضت قال محمود رضا موسى:

 


console.log(document.querySelectorAll('select#products option'));
 

تكون النتيجة فارغة بسبب ان العناصر تم إنشائها وليست عناصر اساسية فهل من حل؟ 

و بالفعل فإن العنصر select بالمعرف products غير موجود من ضمن الDOM . عوضا عن ذلك يوجد بالمعرف product فتكون : 

var productsSelect = document.getElementById('product');

ثم تحتاج إستدعاء الدالة getProducts من المكان الصحيح , أي بعد أي تغير في قائمة الأقسام على هذا النحو :

 <select name="section" 
         onchange="getProducts(this.value)"
         class="form-control 
                                    @error('section')
                                    is-invalid
                                    @enderror" id="section">
        <option value="NULL" disabled>إختر القسم</option>

أو أيضا :

document.getElementById('section').addEventListener('change' ,getProducts(this.value));

فيكون كود الجافاسكربت كاملا على هذا النحو :

var productsSelect = document.getElementById('product');
document.getElementById('section').addEventListener('change' ,getProducts(this.value));

function getProducts(target) {
  let getProducts = new XMLHttpRequest();
  getProducts.open('GET', '/invoices/getProducts/' + target);

  getProducts.onload = function() {
    if (this.readyState === 4 && this.status === 200) { // succes
      let products = JSON.parse(this.responseText);
      products.forEach(function(item) {
        let option = document.createElement('option'),
            text = document.createTextNode(item['product_name']);
        option.appendChild(text);
        option.value = item['id'];
        productsSelect.appendChild(option);
      });
    } else {
      alert('لقد حدث خطأ غير متوقع');
    }
  }

  getProducts.send();
}

 

  • 0
نشر

كما وضح يوسف في التعليق السابق فما تريد هنا يسمى event delegation ولكن ماذا يحل هذا المصطلح ؟ 

كما قلت فالعنصر لم  يكن موجود عند إنشاء ال DOM لذلك عندما قمت بطباعة العنصر 

console.log(document.querySelectorAll('select#products option'));

لم يظهر شئ لذلك الحل يكون عن طريق وضع ال event على العنصر الأب لأنه موجود وسيتم إضافة نفس ال event للعناصر بداخله وذلك يسمى event bubbling 

إذا لا تقوم بإضافة الحدث لل options بل للعنصر الأب وهو في حالتك ال "select#products"(إذا كان موجود في ال DOM مسبقاً)

فمثلاً تريد إضافة الحدث click لل options ستقوم بإضافة هذا الحدث لل select#products كالتالي

document.querySelector('select#products').on('click',function(event){
  //event.target عن طريق options  يمكنك هنا تحديد الحدث لل 
  if(event.target.tagName === "OPTION" ){
     	//your code
     }
)

 

  • 0
نشر

تحديث :

بتاريخ منذ ساعة مضت قال محمود رضا موسى:

عندما اريد تنفيذ حدث معين على الoptions المضافة لا يمكن بسبب ان هذه العناصر غير مقروئة في الجافا سكربت.. اعني انها تكون مقروئة بشكل عادي جدا في الpage source ولكن عندما اقوم بكتابة 

يمكنك أيضا إضافة الevents المتعلقة بالخيارات المنشئة بعد إضافتها . 

مثال : 

function setListeners(){
   
  document.querySelectorAll('select#products option').addEventListener('click' ,function(){
  
     //
  
  });
   
}

ومن ثم إنشاء الأحداث بعد إنشاء العناصر : 

function getProducts(target) {
  let getProducts = new XMLHttpRequest();
  getProducts.open('GET', '/invoices/getProducts/' + target);

  getProducts.onload = function() {
    if (this.readyState === 4 && this.status === 200) { // succes
      let products = JSON.parse(this.responseText);
      products.forEach(function(item) {
        let option = document.createElement('option'),
            text = document.createTextNode(item['product_name']);
        option.appendChild(text);
        option.value = item['id'];
        productsSelect.appendChild(option);
      });
      
      setListeners(); // إستدعاء الدالة
    } else {
      alert('لقد حدث خطأ غير متوقع');
    }
  }

  getProducts.send();
}

 

  • -1
نشر

الفكرة أخي الكريم أن الأوبشن الجديدة لن يتم الإستماع إليها لأن ال DOM تم تحميلها بالفعل ولذلك يجب علينا أن نجعل الجافا إسكربت تقوم بالإستماع لأي شئ جديد عن طريق أكتر من حل :

$(document).delegate('#section', 'change', function (e) {
    // write your code here
});

أو عن طريق دالة ال on

$(document).on('change', '#section', function() {
   // write your code here
});

 

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...